/AzureTableStorage/src/ApplicationSettingsManager/DynamicMethods.cs

# · C# · 469 lines · 234 code · 81 blank · 154 comment · 87 complexity · f0c7875e882c2dbf60f3180ce850b133 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Reflection;
  5. namespace ApplicationSettingsManager
  6. {
  7. public static class DynamicObjectMethods
  8. {
  9. /// <summary>
  10. /// Gets the dynamic property value.
  11. /// This method looks for the property by name in the dynamic object
  12. /// and retrieves the value of that property if found
  13. /// </summary>
  14. /// <param name="propertyName">Name of the property.</param>
  15. /// <param name="dynObject">The dyn object.</param>
  16. /// <returns></returns>
  17. public static dynamic GetObjectPropertyValue(string propertyName, dynamic dynObject)
  18. {
  19. PropertyInfo property = dynObject.GetType().GetProperty(propertyName);
  20. return property == null ? null : property.GetValue(dynObject, null);
  21. }
  22. /// <summary>
  23. /// Calls the method.
  24. /// </summary>
  25. /// <param name="objectType">Type of the object that contains the method.</param>
  26. /// <param name="methodName">Name of the method.</param>
  27. /// <param name="sourceRow">The source row to search for parameters in.</param>
  28. /// <returns></returns>
  29. public static dynamic CallMethod(Type objectType, string methodName, DataRow sourceRow)
  30. {
  31. var methodInfo = objectType.GetMethod(methodName);
  32. var parameters = new List<object>();
  33. methodInfo.GetParameters();
  34. foreach (var param in methodInfo.GetParameters())
  35. {
  36. var name = param.Name;
  37. object value = null;
  38. if (sourceRow.Table.Columns.Contains(name))
  39. value = GetValueFromColumn(sourceRow[name]);
  40. ;
  41. parameters.Add(value);
  42. }
  43. return methodInfo.Invoke(null, parameters.ToArray());
  44. }
  45. /// <summary>
  46. /// Calls the method.
  47. /// </summary>
  48. /// <param name="objectType">Type of the object that contains the method.</param>
  49. /// <param name="methodName">Name of the method.</param>
  50. /// <param name="sourceParams"></param>
  51. /// <returns></returns>
  52. public static dynamic CallMethod(Type objectType, string methodName, dynamic sourceParams)
  53. {
  54. var methodInfo = objectType.GetMethod(methodName);
  55. var parameters = new List<object>();
  56. methodInfo.GetParameters();
  57. foreach (var param in methodInfo.GetParameters())
  58. {
  59. var value = DynamicObjectMethods.GetObjectPropertyValue(param.Name, sourceParams);
  60. parameters.Add(value);
  61. }
  62. return methodInfo.Invoke(null, parameters.ToArray());
  63. }
  64. /// <summary>
  65. /// Sets the list object values for type T; List of T or Array of T[].
  66. /// </summary>
  67. /// <param name="trgtPropInfo">The Target property info.</param>
  68. /// <param name="sourceList">The source list or array of type T.</param>
  69. /// <returns></returns>
  70. public static dynamic SetListObjectValues(PropertyInfo trgtPropInfo, dynamic sourceList, int mType)
  71. {
  72. dynamic targetList; // empty list object of type T
  73. dynamic targetListObjectType; // type T of list object property
  74. dynamic target; // object of type T
  75. // get the property type of the list object type T; List<T> / T[]
  76. dynamic targetListPropertyType = trgtPropInfo.PropertyType;
  77. // targetList is an Array T[].
  78. if (targetListPropertyType.IsArray)
  79. {
  80. //get the target property type that is the array object type T
  81. targetListObjectType = targetListPropertyType.GetElementType();
  82. // instantiate an empty array list of the object type
  83. targetList = Array.CreateInstance(targetListObjectType, sourceList.Count);
  84. var i = 0;
  85. foreach (var source in sourceList)
  86. {
  87. // instantiate the object that is the list object type T
  88. target = Activator.CreateInstance(targetListObjectType);
  89. //if unable to instantiate the list object, skip
  90. if (target == null) continue;
  91. dynamic addObject = mType == 1 ? SetServiceTargetPropertyValues(target, source) : GetServiceSourcePropertyValues(target, source);
  92. //array[i] = item as typeof(type);
  93. targetList[i] = addObject;
  94. i++;
  95. }
  96. }
  97. else // targetList is a List<T>.
  98. {
  99. // instantiate an empty List<T> of the object type
  100. targetList = Activator.CreateInstance(trgtPropInfo.PropertyType);
  101. //get the target property type that is the List<T> object type T
  102. targetListObjectType = targetList.GetType().GetProperty("Item").PropertyType;
  103. foreach (var source in sourceList)
  104. {
  105. // instantiate the object that is the list object type T
  106. target = Activator.CreateInstance(targetListObjectType);
  107. //if unable to instantiate the list object, skip
  108. if (target == null) continue;
  109. dynamic addObject = mType == 1 ? SetServiceTargetPropertyValues(target, source) : GetServiceSourcePropertyValues(target, source);
  110. targetList.Add(addObject);
  111. }
  112. }
  113. return targetList;
  114. }
  115. /// <summary>
  116. /// Sets the target property values.
  117. /// This method loops through the source properties and gets
  118. /// the equivalent target property.
  119. /// If the property is found in the target object,
  120. /// that properties value is set in the target objects property.
  121. /// </summary>
  122. /// <param name="target">The Service (empty) target object.</param>
  123. /// <param name="source">The Local (data filled) source object.</param>
  124. /// <returns>
  125. /// The property value (data) filled target object
  126. /// </returns>
  127. public static dynamic SetServiceTargetPropertyValues(dynamic target, dynamic source)
  128. {
  129. //loop through all source object properties declared
  130. foreach (var srcProperty in source.GetType().GetProperties())
  131. {
  132. // get the source object property value
  133. var propertyValue = srcProperty.GetValue(source, null);
  134. // Check of the source property value is null.
  135. // This enables nullable (OPTIONAL) fields
  136. // to be ignored if no value is present at runtime
  137. if (propertyValue == null) continue;
  138. // Get the equivalent target object property
  139. var trgtProperty = target.GetType().GetProperty(srcProperty.Name);
  140. // Check of the target property is null (does not exist).
  141. // This is a guarantee if the target property sdoes not exist
  142. // we do not attempt to pass a value to it.
  143. if (trgtProperty == null) continue;
  144. // Check if the current target property and the source property are user defined objects with properties
  145. // if so, use recursion to fill all levels of objects in the target object
  146. if (IsUserDefinedObject(trgtProperty.PropertyType, srcProperty.PropertyType))
  147. {
  148. if (trgtProperty.PropertyType.IsArray)
  149. {
  150. //get the target property type that is the list object
  151. var tpType = trgtProperty.PropertyType.GetElementType();
  152. // did we get the target property type?
  153. if (tpType == null) continue;
  154. trgtProperty.SetValue(target, SetListObjectValues(trgtProperty, propertyValue, 1), null);
  155. }
  156. else if ((srcProperty.PropertyType.IsEnum) && (trgtProperty.PropertyType == typeof(string)))
  157. { //the source is an enum and the target is not
  158. // recursion is not necessary, get string value of enum
  159. trgtProperty.SetValue(target, propertyValue.ToString(), null);
  160. }
  161. else if ((srcProperty.PropertyType == typeof(string)) && (trgtProperty.PropertyType.IsEnum))
  162. { //the source is a string value and the target is an enum type
  163. // recursion is not necessary, set the value of enum with string value
  164. trgtProperty.SetValue(target, Enum.Parse(trgtProperty.PropertyType, propertyValue), null);
  165. }
  166. else
  167. {
  168. // instantiate the object that is the property type
  169. var nestObject = trgtProperty.PropertyType.InvokeMember(trgtProperty.Name, BindingFlags.CreateInstance, null, null, null);
  170. // did we get the nested class object?
  171. if (nestObject == null) continue;
  172. // recurse through the new objects
  173. trgtProperty.SetValue(target, SetServiceTargetPropertyValues(nestObject, propertyValue), null);
  174. }
  175. }
  176. else //set the System Property value in the Web Service Object
  177. trgtProperty.SetValue(target, propertyValue, null);
  178. }
  179. return target;
  180. }
  181. /// <summary>
  182. /// Gets the source property values.
  183. /// This method loops through the target object's properties and gets the
  184. /// equivalent source property.
  185. /// If the property is found in the source object,
  186. /// that properties value is set in the target objects property.
  187. /// </summary>
  188. /// <param name="target">The (empty) target object.</param>
  189. /// <param name="source">The data filled web service source object.</param>
  190. /// <returns>
  191. /// The property value (data) filled target object
  192. /// </returns>
  193. public static dynamic GetServiceCamelCaseSourcePropertyValues(dynamic target, dynamic source)
  194. {
  195. //loop through all properties declared in the dynamic target object
  196. foreach (var trgtProperty in target.GetType().GetProperties())
  197. {
  198. string propertyName = trgtProperty.Name;
  199. bool found = false;
  200. // find the equivalent source object property
  201. var srcProperty = source.GetType().GetProperty(MakeCamelCase(propertyName));
  202. if (srcProperty != null)
  203. found = true;
  204. if (!found)
  205. srcProperty = source.GetType().GetProperty(trgtProperty.Name);
  206. if (srcProperty != null)
  207. found = true;
  208. if (!found)
  209. srcProperty = source.GetType().GetProperty(propertyName.ToLower());
  210. // Check of the property is null (does not exist).
  211. if (srcProperty == null) continue;
  212. // get the source object property value
  213. var propertyValue = srcProperty.GetValue(source, null);
  214. // Check of the property value is null.
  215. if (propertyValue == null) continue;
  216. // Check if the current target property and the source property are user defined objects with properties
  217. // if so, use recursion to fill all levels of objects in the target object
  218. if (IsUserDefinedObject(srcProperty.PropertyType, trgtProperty.PropertyType))
  219. {
  220. if (srcProperty.PropertyType.IsArray)
  221. {
  222. trgtProperty.SetValue(target, SetListObjectValues(trgtProperty, propertyValue, 2), null);
  223. }
  224. else if ((srcProperty.PropertyType.IsEnum) && (trgtProperty.PropertyType == typeof(string)))
  225. { //the source is an enum and the target is not
  226. // recursion is not necessary, get string value of enum
  227. trgtProperty.SetValue(target, propertyValue.ToString(), null);
  228. }
  229. //else if ((srcProperty.PropertyType.IsEnum) && (trgtProperty.PropertyType.IsEnum))
  230. //{ //both properties are enums
  231. // // recurse through the enum objects
  232. // trgtProperty.SetValue(target, propertyValue, null);
  233. //}
  234. else
  235. {
  236. // instantiate the object that is the property type
  237. var nestObject = trgtProperty.PropertyType.InvokeMember(trgtProperty.Name, BindingFlags.CreateInstance, null, null, null);
  238. // did we get the nested class object?
  239. if (nestObject == null) continue;
  240. // recurse through the new objects
  241. trgtProperty.SetValue(target, GetServiceSourcePropertyValues(nestObject, propertyValue), null);
  242. }
  243. }
  244. else //set the System Property value in the Web Service Object
  245. trgtProperty.SetValue(target, propertyValue, null);
  246. }
  247. return target;
  248. }
  249. /// <summary>
  250. /// Gets the service source property values.
  251. /// This method loops through the target object's properties and gets the
  252. /// equivalent source property.
  253. /// If the property is found in the source object,
  254. /// that properties value is set in the target objects property.
  255. /// </summary>
  256. /// <param name="target">The (empty) target object.</param>
  257. /// <param name="source">The data filled web service source object.</param>
  258. /// The property value (data) filled target object
  259. /// <returns></returns>
  260. public static dynamic GetServiceSourcePropertyValues(dynamic target, dynamic source)
  261. {
  262. //loop through all properties declared in the dynamic target object
  263. foreach (var trgtProperty in target.GetType().GetProperties())
  264. {
  265. // find the equivalent source object property
  266. var srcProperty = source.GetType().GetProperty(trgtProperty.Name);
  267. // Check of the property is null (does not exist).
  268. // This makes a guarantee if property does not exist
  269. // we do not attempt to get a value from it.
  270. if (srcProperty == null) continue;
  271. // get the source object property value
  272. var propertyValue = srcProperty.GetValue(source, null);
  273. // Check of the property value is null.
  274. // This makes a guarantee if property value does not exist
  275. // we do not attempt to get a value from it.
  276. if (propertyValue == null) continue;
  277. // Check if the current target property and the source property are user defined objects with properties
  278. // if so, use recursion to fill all levels of objects in the target object
  279. if (IsUserDefinedObject(srcProperty.PropertyType, trgtProperty.PropertyType))
  280. {
  281. if (srcProperty.PropertyType.IsArray)
  282. {
  283. trgtProperty.SetValue(target, SetListObjectValues(trgtProperty, propertyValue, 2), null);
  284. }
  285. else if ((srcProperty.PropertyType.IsEnum) && (trgtProperty.PropertyType == typeof(string)))
  286. { //the source is an enum and the target is not
  287. // recursion is not necessary, get string value of enum
  288. trgtProperty.SetValue(target, propertyValue.ToString(), null);
  289. }
  290. //else if ((srcProperty.PropertyType.IsEnum) && (trgtProperty.PropertyType.IsEnum))
  291. //{ //both properties are enums
  292. // // recurse through the enum objects
  293. // trgtProperty.SetValue(target, propertyValue, null);
  294. //}
  295. else
  296. {
  297. // instantiate the object that is the property type
  298. var nestObject = trgtProperty.PropertyType.InvokeMember(trgtProperty.Name, BindingFlags.CreateInstance, null, null, null);
  299. // did we get the nested class object?
  300. if (nestObject == null) continue;
  301. // recurse through the new objects
  302. trgtProperty.SetValue(target, GetServiceSourcePropertyValues(nestObject, propertyValue), null);
  303. }
  304. }
  305. else //set the System Property value in the Web Service Object
  306. trgtProperty.SetValue(target, propertyValue, null);
  307. }
  308. return target;
  309. }
  310. /// <summary>
  311. /// Determines if the properties are class object types and need recursion.
  312. /// If this method is failing,
  313. /// ensure the FBMC user defined objects are created properly
  314. /// </summary>
  315. /// <param name="trgtPropType">Type of the target property.</param>
  316. /// <param name="srcPropType">Type of the source property.</param>
  317. /// <returns></returns>
  318. public static bool IsUserDefinedObject(Type trgtPropType, Type srcPropType)
  319. {
  320. // the namespace of the defined objects
  321. var trgNamespace = trgtPropType.Namespace;
  322. var srcNamespace = srcPropType.Namespace;
  323. // both Objects are System defined objects
  324. if ((trgNamespace == "System") && (srcNamespace == "System")) return false;
  325. // both Objects are "User" defined (i.e. not "System" defined objects)
  326. if ((!trgNamespace.Contains("System.")) && (!srcNamespace.Contains("System.")))
  327. return true;
  328. // see if either object is a "User" defined object
  329. if ((!trgNamespace.Contains("System.")) || (!srcNamespace.Contains("System.")))
  330. {
  331. /***** at least one object is user defined *****/
  332. // see if either object is an enumeration
  333. if ((trgtPropType.IsEnum) || (srcPropType.IsEnum))
  334. return true;
  335. // see if both objects are an array or a list
  336. if (((trgtPropType.IsArray) || (trgtPropType.IsSerializable))
  337. && ((srcPropType.IsArray) || (srcPropType.IsSerializable)))
  338. return true;
  339. }
  340. // both objects are system defined objects and not enums
  341. // no recursion is necessary
  342. return false;
  343. }
  344. /// <summary>
  345. /// Gets the value from column.
  346. /// </summary>
  347. /// <param name="value">The value.</param>
  348. /// <returns></returns>
  349. public static dynamic GetValueFromColumn(object value)
  350. {
  351. if (Convert.IsDBNull(value)) return null;
  352. var rtnValue = default(dynamic);
  353. if (value is string)
  354. rtnValue = Convert.ToString(value);
  355. else if (value is int)
  356. rtnValue = Convert.ToInt32(value);
  357. else if (value is DateTime)
  358. rtnValue = Convert.ToDateTime(value);
  359. else if (value is decimal)
  360. rtnValue = Convert.ToDecimal(value);
  361. return rtnValue;
  362. }
  363. private static string MakePascalCase(string inStr)
  364. {
  365. if (inStr.Length > 0)
  366. {
  367. if (inStr.ToUpper() == "ID") // Always return an ID as a capped field
  368. return inStr.ToUpper();
  369. //convert the first letter in the word to uppercase
  370. char firstLetter = char.ToUpper(inStr[0]);
  371. //concantenate the uppercase letter to the rest of the word
  372. inStr = firstLetter + inStr.Substring(1);
  373. }
  374. return inStr;
  375. }
  376. private static string MakeCamelCase(string inStr)
  377. {
  378. if (inStr.Length > 0)
  379. {
  380. //convert the first letter in the word to uppercase
  381. char firstLetter = char.ToLower(inStr[0]);
  382. //concantenate the uppercase letter to the rest of the word
  383. inStr = firstLetter + inStr.Substring(1);
  384. }
  385. return inStr;
  386. }
  387. }
  388. }