TypeHelpers.cs (10807B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="TypeHelpers.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.Management.Configuration.Processor.Helpers 8 { 9 using System; 10 using System.Collections; 11 using System.Collections.Generic; 12 using System.Reflection; 13 using Microsoft.Management.Configuration.Processor.Exceptions; 14 using Microsoft.Management.Configuration.Processor.Extensions; 15 using Microsoft.Management.Configuration.SetProcessorFactory; 16 using Windows.Foundation.Collections; 17 18 /// <summary> 19 /// Type helpers. 20 /// </summary> 21 internal static class TypeHelpers 22 { 23 /// <summary> 24 /// Verifies a property exists. 25 /// </summary> 26 /// <param name="obj">Dynamic object.</param> 27 /// <param name="name">Name of property.</param> 28 /// <returns>True if property exists.</returns> 29 public static bool PropertyExists(dynamic obj, string name) 30 { 31 return obj.GetType().GetProperty(name) is not null; 32 } 33 34 /// <summary> 35 /// Verifies a property exists with the specified type. 36 /// </summary> 37 /// <typeparam name="TType">Expected type.</typeparam> 38 /// <param name="obj">Dynamic object.</param> 39 /// <param name="name">Name of property.</param> 40 /// <returns>True if property and is of the specified type.</returns> 41 public static bool PropertyWithTypeExists<TType>(dynamic obj, string name) 42 { 43 return PropertyExists(obj, name) && 44 obj.GetType().GetProperty(name).PropertyType == typeof(TType); 45 } 46 47 /// <summary> 48 /// Verifies the property exist and is an enum. 49 /// </summary> 50 /// <param name="obj">Dynamic object.</param> 51 /// <param name="name">Name of property.</param> 52 /// <returns>True if property exists and is an enum.</returns> 53 public static bool PropertyExistsAndIsEnum(dynamic obj, string name) 54 { 55 return PropertyExists(obj, name) && 56 obj.GetType().GetProperty(name).PropertyType.IsEnum; 57 } 58 59 /// <summary> 60 /// Verifies the property exists and is a list. Use this when you don't know the type of the List. 61 /// </summary> 62 /// <param name="obj">Dynamic object.</param> 63 /// <param name="name">Name of property.</param> 64 /// <returns>True if property exists and is a list.</returns> 65 public static bool PropertyExistsAndIsList(dynamic obj, string name) 66 { 67 return PropertyExists(obj, name) && 68 obj.GetType().GetProperty(name).PropertyType.IsGenericType && 69 obj.GetType().GetProperty(name).PropertyType.GetGenericTypeDefinition() == typeof(List<>); 70 } 71 72 /// <summary> 73 /// Gets all the properties and values from an object. 74 /// </summary> 75 /// <param name="obj">Object.</param> 76 /// <returns>ValueSet with properties names and values.</returns> 77 public static ValueSet GetAllPropertiesValues(object obj) 78 { 79 var result = new ValueSet(); 80 foreach (PropertyInfo property in obj.GetType().GetProperties()) 81 { 82 var key = property.Name; 83 var value = GetCompatibleValueSetValueOfProperty(property.PropertyType, property.GetValue(obj)); 84 result.Add(key, value); 85 } 86 87 return result; 88 } 89 90 /// <summary> 91 /// Gets a compatible type for a ValueSet value. 92 /// </summary> 93 /// <param name="type">Type.</param> 94 /// <param name="value">Value.</param> 95 /// <returns>Value converted to a compatible type.</returns> 96 public static object? GetCompatibleValueSetValueOfProperty(Type type, object? value) 97 { 98 if (value == null) 99 { 100 return null; 101 } 102 103 // Specialize here. 104 if (type.IsEnum) 105 { 106 return value.ToString(); 107 } 108 else if (type == typeof(Hashtable)) 109 { 110 Hashtable hashtable = (Hashtable)value; 111 return hashtable.ToValueSet(); 112 } 113 else if (type.IsArray) 114 { 115 var valueSetArray = new ValueSet(); 116 int index = 0; 117 foreach (object arrayObj in (Array)value) 118 { 119 var arrayValue = GetCompatibleValueSetValueOfProperty(arrayObj.GetType(), arrayObj); 120 if (arrayValue != null) 121 { 122 valueSetArray.Add(index.ToString(), arrayValue); 123 index++; 124 } 125 } 126 127 if (valueSetArray.Count > 0) 128 { 129 valueSetArray.Add("treatAsArray", true); 130 } 131 132 return valueSetArray; 133 } 134 else if (type == typeof(string)) 135 { 136 // Ignore empty strings. 137 string propertyString = (string)value; 138 if (!string.IsNullOrEmpty(propertyString)) 139 { 140 return propertyString; 141 } 142 else 143 { 144 return null; 145 } 146 } 147 else if (type.IsValueType) 148 { 149 return value; 150 } 151 152 // This might be too restrictive but anything else is going to be some object that we don't support anyway. 153 throw new UnitPropertyUnsupportedException(value.GetType()); 154 } 155 156 /// <summary> 157 /// Converts PowerShellConfigurationProcessorPolicy string value to PwshConfigurationProcessorPolicy. 158 /// </summary> 159 /// <param name="value">PowerShellConfigurationProcessorPolicy value.</param> 160 /// <returns>PwshConfigurationProcessorPolicy.</returns> 161 public static PwshConfigurationProcessorPolicy ToPwshConfigurationProcessorPolicy(PowerShellConfigurationProcessorPolicy value) 162 { 163 return value switch 164 { 165 PowerShellConfigurationProcessorPolicy.Unrestricted => PwshConfigurationProcessorPolicy.Unrestricted, 166 PowerShellConfigurationProcessorPolicy.RemoteSigned => PwshConfigurationProcessorPolicy.RemoteSigned, 167 PowerShellConfigurationProcessorPolicy.AllSigned => PwshConfigurationProcessorPolicy.AllSigned, 168 PowerShellConfigurationProcessorPolicy.Restricted => PwshConfigurationProcessorPolicy.Restricted, 169 PowerShellConfigurationProcessorPolicy.Bypass => PwshConfigurationProcessorPolicy.Bypass, 170 PowerShellConfigurationProcessorPolicy.Undefined => PwshConfigurationProcessorPolicy.Undefined, 171 _ => throw new InvalidOperationException(), 172 }; 173 } 174 175 /// <summary> 176 /// Converts PwshConfigurationProcessorPolicy string value to PowerShellConfigurationProcessorPolicy. 177 /// </summary> 178 /// <param name="value">PwshConfigurationProcessorPolicy value.</param> 179 /// <returns>PowerShellConfigurationProcessorPolicy.</returns> 180 public static PowerShellConfigurationProcessorPolicy ToPowerShellConfigurationProcessorPolicy(PwshConfigurationProcessorPolicy value) 181 { 182 return value switch 183 { 184 PwshConfigurationProcessorPolicy.Unrestricted => PowerShellConfigurationProcessorPolicy.Unrestricted, 185 PwshConfigurationProcessorPolicy.RemoteSigned => PowerShellConfigurationProcessorPolicy.RemoteSigned, 186 PwshConfigurationProcessorPolicy.AllSigned => PowerShellConfigurationProcessorPolicy.AllSigned, 187 PwshConfigurationProcessorPolicy.Restricted => PowerShellConfigurationProcessorPolicy.Restricted, 188 PwshConfigurationProcessorPolicy.Bypass => PowerShellConfigurationProcessorPolicy.Bypass, 189 PwshConfigurationProcessorPolicy.Undefined => PowerShellConfigurationProcessorPolicy.Undefined, 190 _ => throw new InvalidOperationException(), 191 }; 192 } 193 194 /// <summary> 195 /// Converts PowerShellConfigurationProcessorLocation string value to PwshConfigurationProcessorLocation. 196 /// </summary> 197 /// <param name="value">PowerShellConfigurationProcessorLocation value.</param> 198 /// <returns>PwshConfigurationProcessorLocation.</returns> 199 public static PwshConfigurationProcessorLocation ToPwshConfigurationProcessorLocation(PowerShellConfigurationProcessorLocation value) 200 { 201 return value switch 202 { 203 PowerShellConfigurationProcessorLocation.CurrentUser => PwshConfigurationProcessorLocation.CurrentUser, 204 PowerShellConfigurationProcessorLocation.AllUsers => PwshConfigurationProcessorLocation.AllUsers, 205 PowerShellConfigurationProcessorLocation.WinGetModulePath => PwshConfigurationProcessorLocation.WinGetModulePath, 206 PowerShellConfigurationProcessorLocation.Custom => PwshConfigurationProcessorLocation.Custom, 207 _ => throw new InvalidOperationException(), 208 }; 209 } 210 211 /// <summary> 212 /// Converts PwshConfigurationProcessorLocation string value to PowerShellConfigurationProcessorLocation. 213 /// </summary> 214 /// <param name="value">PwshConfigurationProcessorLocation value.</param> 215 /// <returns>PowerShellConfigurationProcessorLocation.</returns> 216 public static PowerShellConfigurationProcessorLocation ToPowerShellConfigurationProcessorLocation(PwshConfigurationProcessorLocation value) 217 { 218 return value switch 219 { 220 PwshConfigurationProcessorLocation.CurrentUser => PowerShellConfigurationProcessorLocation.CurrentUser, 221 PwshConfigurationProcessorLocation.AllUsers => PowerShellConfigurationProcessorLocation.AllUsers, 222 PwshConfigurationProcessorLocation.WinGetModulePath => PowerShellConfigurationProcessorLocation.WinGetModulePath, 223 PwshConfigurationProcessorLocation.Custom => PowerShellConfigurationProcessorLocation.Custom, 224 _ => throw new InvalidOperationException(), 225 }; 226 } 227 } 228 }