PageRenderTime 48ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/Assets/AWSSDK/src/Services/DynamoDBv2/Custom/DataModel/Utils.cs

https://gitlab.com/vectorci/aws-sdk-unity
C# | 355 lines | 297 code | 39 blank | 19 comment | 61 complexity | 5fafe96bac29588b80ec4cc3c773c85d MD5 | raw file
  1. //
  2. // Copyright 2014-2015 Amazon.com,
  3. // Inc. or its affiliates. All Rights Reserved.
  4. //
  5. // Licensed under the Amazon Software License (the "License").
  6. // You may not use this file except in compliance with the
  7. // License. A copy of the License is located at
  8. //
  9. // http://aws.amazon.com/asl/
  10. //
  11. // or in the "license" file accompanying this file. This file is
  12. // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  13. // CONDITIONS OF ANY KIND, express or implied. See the License
  14. // for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. using System;
  18. using System.Collections.Generic;
  19. using System.IO;
  20. using System.Linq;
  21. using System.Reflection;
  22. using System.Text;
  23. using Amazon.Util.Internal;
  24. using System.Globalization;
  25. using System.Collections;
  26. using Amazon.DynamoDBv2.DocumentModel;
  27. namespace Amazon.DynamoDBv2.DataModel
  28. {
  29. internal static class Utils
  30. {
  31. #region Type methods
  32. private static readonly Type[] primitiveTypesArray = new Type[]
  33. {
  34. typeof(Boolean),
  35. typeof(Byte),
  36. typeof(Char),
  37. typeof(DateTime),
  38. typeof(Decimal),
  39. typeof(Double),
  40. typeof(int),
  41. typeof(long),
  42. typeof(SByte),
  43. typeof(short),
  44. typeof(Single),
  45. typeof(String),
  46. typeof(uint),
  47. typeof(ulong),
  48. typeof(ushort),
  49. typeof(Guid),
  50. typeof(byte[]),
  51. typeof(MemoryStream),
  52. typeof(Primitive)
  53. };
  54. public static readonly IEnumerable<Type> PrimitiveTypes = new HashSet<Type>(primitiveTypesArray);
  55. private static readonly HashSet<ITypeInfo> PrimitiveTypeInfos = new HashSet<ITypeInfo>(primitiveTypesArray
  56. .Select(p => TypeFactory.GetTypeInfo(p)));
  57. public static bool IsPrimitive(Type type)
  58. {
  59. var typeWrapper = TypeFactory.GetTypeInfo(type);
  60. return PrimitiveTypeInfos.Any(ti => typeWrapper.IsAssignableFrom(ti));
  61. }
  62. public static bool IsPrimitive<T>()
  63. {
  64. return IsPrimitive(typeof(T));
  65. }
  66. public static void ValidatePrimitiveType(Type type)
  67. {
  68. if (!Utils.IsPrimitive(type))
  69. throw new InvalidCastException(string.Format(CultureInfo.InvariantCulture,
  70. "{0} is not a supported Primitive type", type.FullName));
  71. }
  72. public static void ValidatePrimitiveType<T>()
  73. {
  74. ValidatePrimitiveType(typeof(T));
  75. }
  76. public static void ValidateVersionType(Type memberType)
  77. {
  78. var memberTypeWrapper = TypeFactory.GetTypeInfo(memberType);
  79. if (memberTypeWrapper.IsGenericType && memberTypeWrapper.GetGenericTypeDefinition() == typeof(Nullable<>) &&
  80. (memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(Byte))) ||
  81. memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(SByte))) ||
  82. memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(int))) ||
  83. memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(uint))) ||
  84. memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(long))) ||
  85. memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(ulong))) ||
  86. memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(short))) ||
  87. memberTypeWrapper.IsAssignableFrom(TypeFactory.GetTypeInfo(typeof(ushort)))))
  88. {
  89. return;
  90. }
  91. throw new InvalidOperationException("Version property must be of primitive, numeric, integer, nullable type (e.g. int?, long?, byte?)");
  92. }
  93. public static Type GetPrimitiveElementType(Type collectionType)
  94. {
  95. var elementType = Utils.GetElementType(collectionType);
  96. if (elementType != null)
  97. {
  98. Utils.ValidatePrimitiveType(elementType);
  99. return elementType;
  100. }
  101. throw new InvalidOperationException("Unable to determine element type");
  102. }
  103. public static Type GetElementType(Type collectionType)
  104. {
  105. var elementType = collectionType.GetElementType();
  106. if (elementType == null)
  107. {
  108. var collectionTypeInfo = TypeFactory.GetTypeInfo(collectionType);
  109. var genericArguments = collectionTypeInfo.GetGenericArguments();
  110. if (genericArguments != null && genericArguments.Length == 1)
  111. elementType = genericArguments[0];
  112. }
  113. // elementType may be null at this point, meaning that the collectionType isn't a collectionType
  114. return elementType;
  115. }
  116. public static bool ItemsToCollection(Type targetType, IEnumerable<object> items, out object result)
  117. {
  118. result = Utils.Instantiate(targetType);
  119. var ilist = result as IList;
  120. if (ilist != null)
  121. {
  122. foreach (var item in items)
  123. ilist.Add(item);
  124. return true;
  125. }
  126. var targetTypeInfo = TypeFactory.GetTypeInfo(targetType);
  127. var addMethod = targetTypeInfo.GetMethod("Add");
  128. if (addMethod != null)
  129. {
  130. foreach (var item in items)
  131. addMethod.Invoke(result, new object[] { item });
  132. return true;
  133. }
  134. result = null;
  135. return false;
  136. }
  137. #endregion
  138. #region Attribute methods
  139. public static DynamoDBTableAttribute GetTableAttribute(ITypeInfo targetTypeInfo)
  140. {
  141. DynamoDBTableAttribute tableAttribute = GetAttribute(targetTypeInfo) as DynamoDBTableAttribute;
  142. if (tableAttribute == null)
  143. return null;
  144. return tableAttribute;
  145. }
  146. public static DynamoDBAttribute GetAttribute(ITypeInfo targetTypeInfo)
  147. {
  148. if (targetTypeInfo == null) throw new ArgumentNullException("targetTypeInfo");
  149. object[] attributes = targetTypeInfo.GetCustomAttributes(TypeFactory.GetTypeInfo(typeof(DynamoDBAttribute)), true);
  150. return GetSingleDDBAttribute(attributes);
  151. }
  152. public static DynamoDBAttribute GetAttribute(MemberInfo targetMemberInfo)
  153. {
  154. object[] attributes = GetAttributeObjects(targetMemberInfo);
  155. return GetSingleDDBAttribute(attributes);
  156. }
  157. public static List<DynamoDBAttribute> GetAttributes(MemberInfo targetMemberInfo)
  158. {
  159. object[] attObjects = GetAttributeObjects(targetMemberInfo) ?? new object[0];
  160. var attributes = new List<DynamoDBAttribute>();
  161. foreach (var attObj in attObjects)
  162. {
  163. var attribute = attObj as DynamoDBAttribute;
  164. if (attribute != null)
  165. attributes.Add(attribute);
  166. }
  167. return attributes;
  168. }
  169. private static DynamoDBAttribute GetSingleDDBAttribute(object[] attributes)
  170. {
  171. if (attributes.Length == 0)
  172. return null;
  173. if (attributes.Length == 1)
  174. return (attributes[0] as DynamoDBAttribute);
  175. throw new InvalidOperationException("Cannot have multiple DynamoDBAttributes on a single member");
  176. }
  177. private static object[] GetAttributeObjects(MemberInfo targetMemberInfo)
  178. {
  179. if (targetMemberInfo == null) throw new ArgumentNullException("targetMemberInfo");
  180. #if PCL
  181. object[] attributes = targetMemberInfo.GetCustomAttributes(typeof(DynamoDBAttribute), true).ToArray();
  182. #else
  183. object[] attributes = targetMemberInfo.GetCustomAttributes(typeof(DynamoDBAttribute), true);
  184. #endif
  185. return attributes;
  186. }
  187. #endregion
  188. #region Non-DynamoDB utilities
  189. public static string ToLowerCamelCase(string value)
  190. {
  191. if (string.IsNullOrEmpty(value) || char.IsLower(value[0])) return value;
  192. StringBuilder sb = new StringBuilder(value);
  193. sb[0] = char.ToLowerInvariant(sb[0]);
  194. return sb.ToString();
  195. }
  196. private static ITypeInfo[][] validConstructorInputs = new ITypeInfo[][]
  197. {
  198. TypeFactory.EmptyTypes,
  199. };
  200. private static ITypeInfo[][] validConverterConstructorInputs = new ITypeInfo[][]
  201. {
  202. TypeFactory.EmptyTypes,
  203. new ITypeInfo[] { TypeFactory.GetTypeInfo(typeof(DynamoDBContext)) }
  204. };
  205. public static object InstantiateConverter(Type objectType, IDynamoDBContext context)
  206. {
  207. return InstantiateHelper(objectType, validConverterConstructorInputs, new object[] { context });
  208. }
  209. public static object Instantiate(Type objectType)
  210. {
  211. return InstantiateHelper(objectType, validConstructorInputs, null);
  212. }
  213. private static object InstantiateHelper(Type objectType, ITypeInfo[][] validConstructorInputs, object[] optionalInput = null)
  214. {
  215. if (objectType == null)
  216. throw new ArgumentNullException("objectType");
  217. if (!CanInstantiateHelper(objectType, validConstructorInputs))
  218. throw new InvalidOperationException("Cannot instantiate type " + objectType.FullName);
  219. var objectTypeWrapper = TypeFactory.GetTypeInfo(objectType);
  220. var constructors = GetConstructors(objectTypeWrapper, validConverterConstructorInputs).ToList();
  221. if (constructors != null && constructors.Count > 0)
  222. {
  223. foreach (var constructor in constructors)
  224. {
  225. var inputs = constructor.GetParameters();
  226. object[] constructorParameters = inputs.Length == 0 ?
  227. null : optionalInput;
  228. object instance = constructor.Invoke(constructorParameters);
  229. return instance;
  230. }
  231. }
  232. throw new InvalidOperationException("Unable to find valid constructor for type " + objectType.FullName);
  233. }
  234. private static IEnumerable<ConstructorInfo> GetConstructors(ITypeInfo typeInfo, ITypeInfo[][] validConstructorInputs)
  235. {
  236. foreach(var inputTypes in validConstructorInputs)
  237. {
  238. var constructor = typeInfo.GetConstructor(inputTypes);
  239. if (constructor != null)
  240. yield return constructor;
  241. }
  242. }
  243. public static bool CanInstantiate(Type objectType)
  244. {
  245. return CanInstantiateHelper(objectType, validConstructorInputs);
  246. }
  247. public static bool CanInstantiateConverter(Type objectType)
  248. {
  249. return CanInstantiateHelper(objectType, validConverterConstructorInputs);
  250. }
  251. private static bool CanInstantiateHelper(Type objectType, ITypeInfo[][] validConstructorInputs)
  252. {
  253. var objectTypeWrapper = TypeFactory.GetTypeInfo(objectType);
  254. bool candidate =
  255. //objectType.IsPublic &&
  256. objectTypeWrapper.IsClass &&
  257. !objectTypeWrapper.IsInterface &&
  258. !objectTypeWrapper.IsAbstract &&
  259. !objectTypeWrapper.IsGenericTypeDefinition &&
  260. !objectTypeWrapper.ContainsGenericParameters;
  261. if (!candidate)
  262. return false;
  263. // check valid constructor inputs
  264. var constructors = GetConstructors(objectTypeWrapper, validConstructorInputs).ToList();
  265. if (constructors.Count == 0)
  266. return false;
  267. return true;
  268. }
  269. public static Type GetType(MemberInfo member)
  270. {
  271. var pi = member as PropertyInfo;
  272. var fi = member as FieldInfo;
  273. if (pi == null && fi == null)
  274. throw new ArgumentOutOfRangeException("member", "member must be of type PropertyInfo or FieldInfo");
  275. return (pi != null ? pi.PropertyType : fi.FieldType);
  276. }
  277. public static bool IsReadWrite(MemberInfo member)
  278. {
  279. PropertyInfo property = member as PropertyInfo;
  280. FieldInfo field = member as FieldInfo;
  281. if (property != null)
  282. {
  283. return (property.CanRead && property.CanWrite);
  284. }
  285. else if (field != null)
  286. {
  287. return (field.IsPublic && !field.IsLiteral && !field.IsInitOnly);
  288. }
  289. else
  290. {
  291. throw new ArgumentOutOfRangeException("member", "Member must be FieldInfo or PropertyInfo");
  292. }
  293. }
  294. public static bool ImplementsInterface(Type targetType, Type interfaceType)
  295. {
  296. var targetTypeWrapper = TypeFactory.GetTypeInfo(targetType);
  297. var interfaceTypeWrapper = TypeFactory.GetTypeInfo(interfaceType);
  298. if (!interfaceTypeWrapper.IsInterface)
  299. throw new ArgumentOutOfRangeException("interfaceType", "Type is not an interface");
  300. foreach (var inter in targetTypeWrapper.GetInterfaces())
  301. {
  302. var interWrapper = TypeFactory.GetTypeInfo(inter);
  303. if (object.Equals(interWrapper, interfaceTypeWrapper))
  304. return true;
  305. if (interfaceTypeWrapper.IsGenericTypeDefinition && interWrapper.IsGenericType)
  306. {
  307. var generic = interWrapper.GetGenericTypeDefinition();
  308. if (generic == interfaceType)
  309. return true;
  310. }
  311. }
  312. return false;
  313. }
  314. #endregion
  315. }
  316. }