PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Json45r7/Source/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs

https://bitbucket.org/wantstudios/bitbucketclient
C# | 1019 lines | 763 code | 153 blank | 103 comment | 138 complexity | 895d4222e8722ed1317e713dbb35245c MD5 | raw file
  1. #region License
  2. // Copyright (c) 2007 James Newton-King
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. #endregion
  25. using System;
  26. using System.Collections.Generic;
  27. using System.Reflection;
  28. using System.Collections;
  29. using System.Globalization;
  30. using System.Runtime.Serialization;
  31. using System.Runtime.Serialization.Formatters;
  32. using System.Text;
  33. #if NETFX_CORE
  34. using IConvertible = Newtonsoft.Json.Utilities.Convertible;
  35. #endif
  36. #if NETFX_CORE || PORTABLE
  37. using ICustomAttributeProvider = Newtonsoft.Json.Utilities.CustomAttributeProvider;
  38. #endif
  39. #if NET20
  40. using Newtonsoft.Json.Utilities.LinqBridge;
  41. #else
  42. using System.Linq;
  43. #endif
  44. using Newtonsoft.Json.Serialization;
  45. namespace Newtonsoft.Json.Utilities
  46. {
  47. #if NETFX_CORE || PORTABLE
  48. internal enum MemberTypes
  49. {
  50. Property,
  51. Field,
  52. Event,
  53. Method,
  54. Other
  55. }
  56. internal class CustomAttributeProvider
  57. {
  58. private readonly object _underlyingObject;
  59. public CustomAttributeProvider(object o)
  60. {
  61. _underlyingObject = o;
  62. }
  63. public object UnderlyingObject
  64. {
  65. get { return _underlyingObject; }
  66. }
  67. }
  68. #endif
  69. #if NETFX_CORE
  70. internal enum TypeCode
  71. {
  72. Empty,
  73. Object,
  74. String,
  75. Char,
  76. Boolean,
  77. SByte,
  78. Int16,
  79. UInt16,
  80. Int32,
  81. Byte,
  82. UInt32,
  83. Int64,
  84. UInt64,
  85. Single,
  86. Double,
  87. DateTime,
  88. Decimal
  89. }
  90. [Flags]
  91. internal enum BindingFlags
  92. {
  93. Default = 0,
  94. IgnoreCase = 1,
  95. DeclaredOnly = 2,
  96. Instance = 4,
  97. Static = 8,
  98. Public = 16,
  99. NonPublic = 32,
  100. FlattenHierarchy = 64,
  101. InvokeMethod = 256,
  102. CreateInstance = 512,
  103. GetField = 1024,
  104. SetField = 2048,
  105. GetProperty = 4096,
  106. SetProperty = 8192,
  107. PutDispProperty = 16384,
  108. ExactBinding = 65536,
  109. PutRefDispProperty = 32768,
  110. SuppressChangeType = 131072,
  111. OptionalParamBinding = 262144,
  112. IgnoreReturn = 16777216
  113. }
  114. #endif
  115. internal static class ReflectionUtils
  116. {
  117. public static readonly Type[] EmptyTypes;
  118. static ReflectionUtils()
  119. {
  120. #if !(NETFX_CORE || PORTABLE)
  121. EmptyTypes = Type.EmptyTypes;
  122. #else
  123. EmptyTypes = new Type[0];
  124. #endif
  125. }
  126. public static ICustomAttributeProvider GetCustomAttributeProvider(this object o)
  127. {
  128. #if !(NETFX_CORE || PORTABLE)
  129. return (ICustomAttributeProvider)o;
  130. #else
  131. return new ICustomAttributeProvider(o);
  132. #endif
  133. }
  134. public static bool IsVirtual(this PropertyInfo propertyInfo)
  135. {
  136. ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
  137. MethodInfo m = propertyInfo.GetGetMethod();
  138. if (m != null && m.IsVirtual)
  139. return true;
  140. m = propertyInfo.GetSetMethod();
  141. if (m != null && m.IsVirtual)
  142. return true;
  143. return false;
  144. }
  145. public static Type GetObjectType(object v)
  146. {
  147. return (v != null) ? v.GetType() : null;
  148. }
  149. public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat)
  150. {
  151. return GetTypeName(t, assemblyFormat, null);
  152. }
  153. public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat, SerializationBinder binder)
  154. {
  155. string fullyQualifiedTypeName;
  156. #if !(NET20 || NET35)
  157. if (binder != null)
  158. {
  159. string assemblyName, typeName;
  160. binder.BindToName(t, out assemblyName, out typeName);
  161. fullyQualifiedTypeName = typeName + (assemblyName == null ? "" : ", " + assemblyName);
  162. }
  163. else
  164. {
  165. fullyQualifiedTypeName = t.AssemblyQualifiedName;
  166. }
  167. #else
  168. fullyQualifiedTypeName = t.AssemblyQualifiedName;
  169. #endif
  170. switch (assemblyFormat)
  171. {
  172. case FormatterAssemblyStyle.Simple:
  173. return RemoveAssemblyDetails(fullyQualifiedTypeName);
  174. case FormatterAssemblyStyle.Full:
  175. return fullyQualifiedTypeName;
  176. default:
  177. throw new ArgumentOutOfRangeException();
  178. }
  179. }
  180. private static string RemoveAssemblyDetails(string fullyQualifiedTypeName)
  181. {
  182. StringBuilder builder = new StringBuilder();
  183. // loop through the type name and filter out qualified assembly details from nested type names
  184. bool writingAssemblyName = false;
  185. bool skippingAssemblyDetails = false;
  186. for (int i = 0; i < fullyQualifiedTypeName.Length; i++)
  187. {
  188. char current = fullyQualifiedTypeName[i];
  189. switch (current)
  190. {
  191. case '[':
  192. writingAssemblyName = false;
  193. skippingAssemblyDetails = false;
  194. builder.Append(current);
  195. break;
  196. case ']':
  197. writingAssemblyName = false;
  198. skippingAssemblyDetails = false;
  199. builder.Append(current);
  200. break;
  201. case ',':
  202. if (!writingAssemblyName)
  203. {
  204. writingAssemblyName = true;
  205. builder.Append(current);
  206. }
  207. else
  208. {
  209. skippingAssemblyDetails = true;
  210. }
  211. break;
  212. default:
  213. if (!skippingAssemblyDetails)
  214. builder.Append(current);
  215. break;
  216. }
  217. }
  218. return builder.ToString();
  219. }
  220. public static bool IsInstantiatableType(Type t)
  221. {
  222. ValidationUtils.ArgumentNotNull(t, "t");
  223. if (t.IsAbstract() || t.IsInterface() || t.IsArray || t.IsGenericTypeDefinition() || t == typeof(void))
  224. return false;
  225. if (!HasDefaultConstructor(t))
  226. return false;
  227. return true;
  228. }
  229. public static bool HasDefaultConstructor(Type t)
  230. {
  231. return HasDefaultConstructor(t, false);
  232. }
  233. public static bool HasDefaultConstructor(Type t, bool nonPublic)
  234. {
  235. ValidationUtils.ArgumentNotNull(t, "t");
  236. if (t.IsValueType())
  237. return true;
  238. return (GetDefaultConstructor(t, nonPublic) != null);
  239. }
  240. public static ConstructorInfo GetDefaultConstructor(Type t)
  241. {
  242. return GetDefaultConstructor(t, false);
  243. }
  244. public static ConstructorInfo GetDefaultConstructor(Type t, bool nonPublic)
  245. {
  246. BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;
  247. if (nonPublic)
  248. bindingFlags = bindingFlags | BindingFlags.NonPublic;
  249. return t.GetConstructors(bindingFlags).SingleOrDefault(c => !c.GetParameters().Any());
  250. }
  251. public static bool IsNullable(Type t)
  252. {
  253. ValidationUtils.ArgumentNotNull(t, "t");
  254. if (t.IsValueType())
  255. return IsNullableType(t);
  256. return true;
  257. }
  258. public static bool IsNullableType(Type t)
  259. {
  260. ValidationUtils.ArgumentNotNull(t, "t");
  261. return (t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(Nullable<>));
  262. }
  263. public static Type EnsureNotNullableType(Type t)
  264. {
  265. return (IsNullableType(t))
  266. ? Nullable.GetUnderlyingType(t)
  267. : t;
  268. }
  269. public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition)
  270. {
  271. Type implementingType;
  272. return ImplementsGenericDefinition(type, genericInterfaceDefinition, out implementingType);
  273. }
  274. public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, out Type implementingType)
  275. {
  276. ValidationUtils.ArgumentNotNull(type, "type");
  277. ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, "genericInterfaceDefinition");
  278. if (!genericInterfaceDefinition.IsInterface() || !genericInterfaceDefinition.IsGenericTypeDefinition())
  279. throw new ArgumentNullException("'{0}' is not a generic interface definition.".FormatWith(CultureInfo.InvariantCulture, genericInterfaceDefinition));
  280. if (type.IsInterface())
  281. {
  282. if (type.IsGenericType())
  283. {
  284. Type interfaceDefinition = type.GetGenericTypeDefinition();
  285. if (genericInterfaceDefinition == interfaceDefinition)
  286. {
  287. implementingType = type;
  288. return true;
  289. }
  290. }
  291. }
  292. foreach (Type i in type.GetInterfaces())
  293. {
  294. if (i.IsGenericType())
  295. {
  296. Type interfaceDefinition = i.GetGenericTypeDefinition();
  297. if (genericInterfaceDefinition == interfaceDefinition)
  298. {
  299. implementingType = i;
  300. return true;
  301. }
  302. }
  303. }
  304. implementingType = null;
  305. return false;
  306. }
  307. public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition)
  308. {
  309. Type implementingType;
  310. return InheritsGenericDefinition(type, genericClassDefinition, out implementingType);
  311. }
  312. public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type implementingType)
  313. {
  314. ValidationUtils.ArgumentNotNull(type, "type");
  315. ValidationUtils.ArgumentNotNull(genericClassDefinition, "genericClassDefinition");
  316. if (!genericClassDefinition.IsClass() || !genericClassDefinition.IsGenericTypeDefinition())
  317. throw new ArgumentNullException("'{0}' is not a generic class definition.".FormatWith(CultureInfo.InvariantCulture, genericClassDefinition));
  318. return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType);
  319. }
  320. private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type implementingType)
  321. {
  322. if (currentType.IsGenericType())
  323. {
  324. Type currentGenericClassDefinition = currentType.GetGenericTypeDefinition();
  325. if (genericClassDefinition == currentGenericClassDefinition)
  326. {
  327. implementingType = currentType;
  328. return true;
  329. }
  330. }
  331. if (currentType.BaseType() == null)
  332. {
  333. implementingType = null;
  334. return false;
  335. }
  336. return InheritsGenericDefinitionInternal(currentType.BaseType(), genericClassDefinition, out implementingType);
  337. }
  338. /// <summary>
  339. /// Gets the type of the typed collection's items.
  340. /// </summary>
  341. /// <param name="type">The type.</param>
  342. /// <returns>The type of the typed collection's items.</returns>
  343. public static Type GetCollectionItemType(Type type)
  344. {
  345. ValidationUtils.ArgumentNotNull(type, "type");
  346. Type genericListType;
  347. if (type.IsArray)
  348. {
  349. return type.GetElementType();
  350. }
  351. else if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out genericListType))
  352. {
  353. if (genericListType.IsGenericTypeDefinition())
  354. throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
  355. return genericListType.GetGenericArguments()[0];
  356. }
  357. else if (typeof(IEnumerable).IsAssignableFrom(type))
  358. {
  359. return null;
  360. }
  361. else
  362. {
  363. throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
  364. }
  365. }
  366. public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
  367. {
  368. ValidationUtils.ArgumentNotNull(dictionaryType, "type");
  369. Type genericDictionaryType;
  370. if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<,>), out genericDictionaryType))
  371. {
  372. if (genericDictionaryType.IsGenericTypeDefinition())
  373. throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
  374. Type[] dictionaryGenericArguments = genericDictionaryType.GetGenericArguments();
  375. keyType = dictionaryGenericArguments[0];
  376. valueType = dictionaryGenericArguments[1];
  377. return;
  378. }
  379. else if (typeof(IDictionary).IsAssignableFrom(dictionaryType))
  380. {
  381. keyType = null;
  382. valueType = null;
  383. return;
  384. }
  385. else
  386. {
  387. throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
  388. }
  389. }
  390. public static Type GetDictionaryValueType(Type dictionaryType)
  391. {
  392. Type keyType;
  393. Type valueType;
  394. GetDictionaryKeyValueTypes(dictionaryType, out keyType, out valueType);
  395. return valueType;
  396. }
  397. public static Type GetDictionaryKeyType(Type dictionaryType)
  398. {
  399. Type keyType;
  400. Type valueType;
  401. GetDictionaryKeyValueTypes(dictionaryType, out keyType, out valueType);
  402. return keyType;
  403. }
  404. /// <summary>
  405. /// Gets the member's underlying type.
  406. /// </summary>
  407. /// <param name="member">The member.</param>
  408. /// <returns>The underlying type of the member.</returns>
  409. public static Type GetMemberUnderlyingType(MemberInfo member)
  410. {
  411. ValidationUtils.ArgumentNotNull(member, "member");
  412. switch (member.MemberType())
  413. {
  414. case MemberTypes.Field:
  415. return ((FieldInfo)member).FieldType;
  416. case MemberTypes.Property:
  417. return ((PropertyInfo)member).PropertyType;
  418. case MemberTypes.Event:
  419. return ((EventInfo)member).EventHandlerType;
  420. default:
  421. throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or EventInfo", "member");
  422. }
  423. }
  424. /// <summary>
  425. /// Determines whether the member is an indexed property.
  426. /// </summary>
  427. /// <param name="member">The member.</param>
  428. /// <returns>
  429. /// <c>true</c> if the member is an indexed property; otherwise, <c>false</c>.
  430. /// </returns>
  431. public static bool IsIndexedProperty(MemberInfo member)
  432. {
  433. ValidationUtils.ArgumentNotNull(member, "member");
  434. PropertyInfo propertyInfo = member as PropertyInfo;
  435. if (propertyInfo != null)
  436. return IsIndexedProperty(propertyInfo);
  437. else
  438. return false;
  439. }
  440. /// <summary>
  441. /// Determines whether the property is an indexed property.
  442. /// </summary>
  443. /// <param name="property">The property.</param>
  444. /// <returns>
  445. /// <c>true</c> if the property is an indexed property; otherwise, <c>false</c>.
  446. /// </returns>
  447. public static bool IsIndexedProperty(PropertyInfo property)
  448. {
  449. ValidationUtils.ArgumentNotNull(property, "property");
  450. return (property.GetIndexParameters().Length > 0);
  451. }
  452. /// <summary>
  453. /// Gets the member's value on the object.
  454. /// </summary>
  455. /// <param name="member">The member.</param>
  456. /// <param name="target">The target object.</param>
  457. /// <returns>The member's value on the object.</returns>
  458. public static object GetMemberValue(MemberInfo member, object target)
  459. {
  460. ValidationUtils.ArgumentNotNull(member, "member");
  461. ValidationUtils.ArgumentNotNull(target, "target");
  462. switch (member.MemberType())
  463. {
  464. case MemberTypes.Field:
  465. return ((FieldInfo)member).GetValue(target);
  466. case MemberTypes.Property:
  467. try
  468. {
  469. return ((PropertyInfo)member).GetValue(target, null);
  470. }
  471. catch (TargetParameterCountException e)
  472. {
  473. throw new ArgumentException("MemberInfo '{0}' has index parameters".FormatWith(CultureInfo.InvariantCulture, member.Name), e);
  474. }
  475. default:
  476. throw new ArgumentException("MemberInfo '{0}' is not of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, CultureInfo.InvariantCulture, member.Name), "member");
  477. }
  478. }
  479. /// <summary>
  480. /// Sets the member's value on the target object.
  481. /// </summary>
  482. /// <param name="member">The member.</param>
  483. /// <param name="target">The target.</param>
  484. /// <param name="value">The value.</param>
  485. public static void SetMemberValue(MemberInfo member, object target, object value)
  486. {
  487. ValidationUtils.ArgumentNotNull(member, "member");
  488. ValidationUtils.ArgumentNotNull(target, "target");
  489. switch (member.MemberType())
  490. {
  491. case MemberTypes.Field:
  492. ((FieldInfo)member).SetValue(target, value);
  493. break;
  494. case MemberTypes.Property:
  495. ((PropertyInfo)member).SetValue(target, value, null);
  496. break;
  497. default:
  498. throw new ArgumentException("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member");
  499. }
  500. }
  501. /// <summary>
  502. /// Determines whether the specified MemberInfo can be read.
  503. /// </summary>
  504. /// <param name="member">The MemberInfo to determine whether can be read.</param>
  505. /// /// <param name="nonPublic">if set to <c>true</c> then allow the member to be gotten non-publicly.</param>
  506. /// <returns>
  507. /// <c>true</c> if the specified MemberInfo can be read; otherwise, <c>false</c>.
  508. /// </returns>
  509. public static bool CanReadMemberValue(MemberInfo member, bool nonPublic)
  510. {
  511. switch (member.MemberType())
  512. {
  513. case MemberTypes.Field:
  514. FieldInfo fieldInfo = (FieldInfo)member;
  515. if (nonPublic)
  516. return true;
  517. else if (fieldInfo.IsPublic)
  518. return true;
  519. return false;
  520. case MemberTypes.Property:
  521. PropertyInfo propertyInfo = (PropertyInfo) member;
  522. if (!propertyInfo.CanRead)
  523. return false;
  524. if (nonPublic)
  525. return true;
  526. return (propertyInfo.GetGetMethod(nonPublic) != null);
  527. default:
  528. return false;
  529. }
  530. }
  531. /// <summary>
  532. /// Determines whether the specified MemberInfo can be set.
  533. /// </summary>
  534. /// <param name="member">The MemberInfo to determine whether can be set.</param>
  535. /// <param name="nonPublic">if set to <c>true</c> then allow the member to be set non-publicly.</param>
  536. /// <param name="canSetReadOnly">if set to <c>true</c> then allow the member to be set if read-only.</param>
  537. /// <returns>
  538. /// <c>true</c> if the specified MemberInfo can be set; otherwise, <c>false</c>.
  539. /// </returns>
  540. public static bool CanSetMemberValue(MemberInfo member, bool nonPublic, bool canSetReadOnly)
  541. {
  542. switch (member.MemberType())
  543. {
  544. case MemberTypes.Field:
  545. FieldInfo fieldInfo = (FieldInfo)member;
  546. if (fieldInfo.IsInitOnly && !canSetReadOnly)
  547. return false;
  548. if (nonPublic)
  549. return true;
  550. else if (fieldInfo.IsPublic)
  551. return true;
  552. return false;
  553. case MemberTypes.Property:
  554. PropertyInfo propertyInfo = (PropertyInfo)member;
  555. if (!propertyInfo.CanWrite)
  556. return false;
  557. if (nonPublic)
  558. return true;
  559. return (propertyInfo.GetSetMethod(nonPublic) != null);
  560. default:
  561. return false;
  562. }
  563. }
  564. public static List<MemberInfo> GetFieldsAndProperties(Type type, BindingFlags bindingAttr)
  565. {
  566. List<MemberInfo> targetMembers = new List<MemberInfo>();
  567. targetMembers.AddRange(GetFields(type, bindingAttr));
  568. targetMembers.AddRange(GetProperties(type, bindingAttr));
  569. // for some reason .NET returns multiple members when overriding a generic member on a base class
  570. // http://forums.msdn.microsoft.com/en-US/netfxbcl/thread/b5abbfee-e292-4a64-8907-4e3f0fb90cd9/
  571. // filter members to only return the override on the topmost class
  572. // update: I think this is fixed in .NET 3.5 SP1 - leave this in for now...
  573. List<MemberInfo> distinctMembers = new List<MemberInfo>(targetMembers.Count);
  574. foreach (var groupedMember in targetMembers.GroupBy(m => m.Name))
  575. {
  576. int count = groupedMember.Count();
  577. IList<MemberInfo> members = groupedMember.ToList();
  578. if (count == 1)
  579. {
  580. distinctMembers.Add(members.First());
  581. }
  582. else
  583. {
  584. var resolvedMembers = members.Where(m => !IsOverridenGenericMember(m, bindingAttr) || m.Name == "Item");
  585. distinctMembers.AddRange(resolvedMembers);
  586. }
  587. }
  588. return distinctMembers;
  589. }
  590. private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr)
  591. {
  592. MemberTypes memberType = memberInfo.MemberType();
  593. if (memberType != MemberTypes.Field && memberType != MemberTypes.Property)
  594. throw new ArgumentException("Member must be a field or property.");
  595. Type declaringType = memberInfo.DeclaringType;
  596. if (!declaringType.IsGenericType())
  597. return false;
  598. Type genericTypeDefinition = declaringType.GetGenericTypeDefinition();
  599. if (genericTypeDefinition == null)
  600. return false;
  601. MemberInfo[] members = genericTypeDefinition.GetMember(memberInfo.Name, bindingAttr);
  602. if (members.Length == 0)
  603. return false;
  604. Type memberUnderlyingType = GetMemberUnderlyingType(members[0]);
  605. if (!memberUnderlyingType.IsGenericParameter)
  606. return false;
  607. return true;
  608. }
  609. public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider) where T : Attribute
  610. {
  611. return GetAttribute<T>(attributeProvider, true);
  612. }
  613. public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
  614. {
  615. T[] attributes = GetAttributes<T>(attributeProvider, inherit);
  616. return attributes.SingleOrDefault();
  617. }
  618. #if !(NETFX_CORE)
  619. public static T[] GetAttributes<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
  620. {
  621. ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider");
  622. object provider;
  623. #if !PORTABLE
  624. provider = attributeProvider;
  625. #else
  626. provider = attributeProvider.UnderlyingObject;
  627. #endif
  628. // http://hyperthink.net/blog/getcustomattributes-gotcha/
  629. // ICustomAttributeProvider doesn't do inheritance
  630. if (provider is Type)
  631. return (T[])((Type)provider).GetCustomAttributes(typeof(T), inherit);
  632. if (provider is Assembly)
  633. return (T[])Attribute.GetCustomAttributes((Assembly)provider, typeof(T));
  634. if (provider is MemberInfo)
  635. return (T[])Attribute.GetCustomAttributes((MemberInfo)provider, typeof(T), inherit);
  636. #if !PORTABLE
  637. if (provider is Module)
  638. return (T[])Attribute.GetCustomAttributes((Module)provider, typeof(T), inherit);
  639. #endif
  640. if (provider is ParameterInfo)
  641. return (T[])Attribute.GetCustomAttributes((ParameterInfo)provider, typeof(T), inherit);
  642. #if !PORTABLE
  643. return (T[])attributeProvider.GetCustomAttributes(typeof(T), inherit);
  644. #else
  645. throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider));
  646. #endif
  647. }
  648. #else
  649. public static T[] GetAttributes<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
  650. {
  651. object provider = attributeProvider.UnderlyingObject;
  652. if (provider is Type)
  653. return ((Type)provider).GetTypeInfo().GetCustomAttributes<T>(inherit).ToArray();
  654. if (provider is Assembly)
  655. return ((Assembly)provider).GetCustomAttributes<T>().ToArray();
  656. if (provider is MemberInfo)
  657. return ((MemberInfo)provider).GetCustomAttributes<T>(inherit).ToArray();
  658. if (provider is Module)
  659. return ((Module)provider).GetCustomAttributes<T>().ToArray();
  660. if (provider is ParameterInfo)
  661. return ((ParameterInfo)provider).GetCustomAttributes<T>(inherit).ToArray();
  662. throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider));
  663. }
  664. #endif
  665. public static Type MakeGenericType(Type genericTypeDefinition, params Type[] innerTypes)
  666. {
  667. ValidationUtils.ArgumentNotNull(genericTypeDefinition, "genericTypeDefinition");
  668. ValidationUtils.ArgumentNotNullOrEmpty<Type>(innerTypes, "innerTypes");
  669. ValidationUtils.ArgumentConditionTrue(genericTypeDefinition.IsGenericTypeDefinition(), "genericTypeDefinition", "Type {0} is not a generic type definition.".FormatWith(CultureInfo.InvariantCulture, genericTypeDefinition));
  670. return genericTypeDefinition.MakeGenericType(innerTypes);
  671. }
  672. public static object CreateGeneric(Type genericTypeDefinition, Type innerType, params object[] args)
  673. {
  674. return CreateGeneric(genericTypeDefinition, new [] { innerType }, args);
  675. }
  676. public static object CreateGeneric(Type genericTypeDefinition, IList<Type> innerTypes, params object[] args)
  677. {
  678. return CreateGeneric(genericTypeDefinition, innerTypes, (t, a) => CreateInstance(t, a.ToArray()), args);
  679. }
  680. public static object CreateGeneric(Type genericTypeDefinition, IList<Type> innerTypes, Func<Type, IList<object>, object> instanceCreator, params object[] args)
  681. {
  682. ValidationUtils.ArgumentNotNull(genericTypeDefinition, "genericTypeDefinition");
  683. ValidationUtils.ArgumentNotNullOrEmpty(innerTypes, "innerTypes");
  684. ValidationUtils.ArgumentNotNull(instanceCreator, "createInstance");
  685. Type specificType = MakeGenericType(genericTypeDefinition, innerTypes.ToArray());
  686. return instanceCreator(specificType, args);
  687. }
  688. public static object CreateInstance(Type type, params object[] args)
  689. {
  690. ValidationUtils.ArgumentNotNull(type, "type");
  691. #if !PocketPC
  692. return Activator.CreateInstance(type, args);
  693. #else
  694. // CF doesn't have a Activator.CreateInstance overload that takes args
  695. // lame
  696. if (type.IsValueType && CollectionUtils.IsNullOrEmpty<object>(args))
  697. return Activator.CreateInstance(type);
  698. ConstructorInfo[] constructors = type.GetConstructors();
  699. ConstructorInfo match = constructors.Where(c =>
  700. {
  701. ParameterInfo[] parameters = c.GetParameters();
  702. if (parameters.Length != args.Length)
  703. return false;
  704. for (int i = 0; i < parameters.Length; i++)
  705. {
  706. ParameterInfo parameter = parameters[i];
  707. object value = args[i];
  708. if (!IsCompatibleValue(value, parameter.ParameterType))
  709. return false;
  710. }
  711. return true;
  712. }).FirstOrDefault();
  713. if (match == null)
  714. throw new Exception("Could not create '{0}' with given parameters.".FormatWith(CultureInfo.InvariantCulture, type));
  715. return match.Invoke(args);
  716. #endif
  717. }
  718. public static void SplitFullyQualifiedTypeName(string fullyQualifiedTypeName, out string typeName, out string assemblyName)
  719. {
  720. int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName);
  721. if (assemblyDelimiterIndex != null)
  722. {
  723. typeName = fullyQualifiedTypeName.Substring(0, assemblyDelimiterIndex.Value).Trim();
  724. assemblyName = fullyQualifiedTypeName.Substring(assemblyDelimiterIndex.Value + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.Value - 1).Trim();
  725. }
  726. else
  727. {
  728. typeName = fullyQualifiedTypeName;
  729. assemblyName = null;
  730. }
  731. }
  732. private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName)
  733. {
  734. // we need to get the first comma following all surrounded in brackets because of generic types
  735. // e.g. System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
  736. int scope = 0;
  737. for (int i = 0; i < fullyQualifiedTypeName.Length; i++)
  738. {
  739. char current = fullyQualifiedTypeName[i];
  740. switch (current)
  741. {
  742. case '[':
  743. scope++;
  744. break;
  745. case ']':
  746. scope--;
  747. break;
  748. case ',':
  749. if (scope == 0)
  750. return i;
  751. break;
  752. }
  753. }
  754. return null;
  755. }
  756. public static MemberInfo GetMemberInfoFromType(Type targetType, MemberInfo memberInfo)
  757. {
  758. const BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
  759. switch (memberInfo.MemberType())
  760. {
  761. case MemberTypes.Property:
  762. PropertyInfo propertyInfo = (PropertyInfo) memberInfo;
  763. Type[] types = propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray();
  764. return targetType.GetProperty(propertyInfo.Name, bindingAttr, null, propertyInfo.PropertyType, types, null);
  765. default:
  766. return targetType.GetMember(memberInfo.Name, memberInfo.MemberType(), bindingAttr).SingleOrDefault();
  767. }
  768. }
  769. public static IEnumerable<FieldInfo> GetFields(Type targetType, BindingFlags bindingAttr)
  770. {
  771. ValidationUtils.ArgumentNotNull(targetType, "targetType");
  772. List<MemberInfo> fieldInfos = new List<MemberInfo>(targetType.GetFields(bindingAttr));
  773. #if !NETFX_CORE
  774. // Type.GetFields doesn't return inherited private fields
  775. // manually find private fields from base class
  776. GetChildPrivateFields(fieldInfos, targetType, bindingAttr);
  777. #endif
  778. return fieldInfos.Cast<FieldInfo>();
  779. }
  780. private static void GetChildPrivateFields(IList<MemberInfo> initialFields, Type targetType, BindingFlags bindingAttr)
  781. {
  782. // fix weirdness with private FieldInfos only being returned for the current Type
  783. // find base type fields and add them to result
  784. if ((bindingAttr & BindingFlags.NonPublic) != 0)
  785. {
  786. // modify flags to not search for public fields
  787. BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
  788. while ((targetType = targetType.BaseType()) != null)
  789. {
  790. // filter out protected fields
  791. IEnumerable<MemberInfo> childPrivateFields =
  792. targetType.GetFields(nonPublicBindingAttr).Where(f => f.IsPrivate).Cast<MemberInfo>();
  793. initialFields.AddRange(childPrivateFields);
  794. }
  795. }
  796. }
  797. public static IEnumerable<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
  798. {
  799. ValidationUtils.ArgumentNotNull(targetType, "targetType");
  800. List<PropertyInfo> propertyInfos = new List<PropertyInfo>(targetType.GetProperties(bindingAttr));
  801. GetChildPrivateProperties(propertyInfos, targetType, bindingAttr);
  802. // a base class private getter/setter will be inaccessable unless the property was gotten from the base class
  803. for (int i = 0; i < propertyInfos.Count; i++)
  804. {
  805. PropertyInfo member = propertyInfos[i];
  806. if (member.DeclaringType != targetType)
  807. {
  808. PropertyInfo declaredMember = (PropertyInfo)GetMemberInfoFromType(member.DeclaringType, member);
  809. propertyInfos[i] = declaredMember;
  810. }
  811. }
  812. return propertyInfos;
  813. }
  814. public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag)
  815. {
  816. return ((bindingAttr & flag) == flag)
  817. ? bindingAttr ^ flag
  818. : bindingAttr;
  819. }
  820. private static void GetChildPrivateProperties(IList<PropertyInfo> initialProperties, Type targetType, BindingFlags bindingAttr)
  821. {
  822. // fix weirdness with private PropertyInfos only being returned for the current Type
  823. // find base type properties and add them to result
  824. if ((bindingAttr & BindingFlags.NonPublic) != 0)
  825. {
  826. // modify flags to not search for public fields
  827. BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
  828. while ((targetType = targetType.BaseType()) != null)
  829. {
  830. foreach (PropertyInfo propertyInfo in targetType.GetProperties(nonPublicBindingAttr))
  831. {
  832. PropertyInfo nonPublicProperty = propertyInfo;
  833. // have to test on name rather than reference because instances are different
  834. // depending on the type that GetProperties was called on
  835. int index = initialProperties.IndexOf(p => p.Name == nonPublicProperty.Name);
  836. if (index == -1)
  837. {
  838. initialProperties.Add(nonPublicProperty);
  839. }
  840. else
  841. {
  842. // replace nonpublic properties for a child, but gotten from
  843. // the parent with the one from the child
  844. // the property gotten from the child will have access to private getter/setter
  845. initialProperties[index] = nonPublicProperty;
  846. }
  847. }
  848. }
  849. }
  850. }
  851. public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType, string method)
  852. {
  853. bool isMethodOverriden = currentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
  854. .Any(info =>
  855. info.Name == method &&
  856. // check that the method overrides the original on DynamicObjectProxy
  857. info.DeclaringType != methodDeclaringType
  858. // todo - find out whether there is a way to do this in winrt
  859. #if !NETFX_CORE
  860. && info.GetBaseDefinition().DeclaringType == methodDeclaringType
  861. #endif
  862. );
  863. return isMethodOverriden;
  864. }
  865. }
  866. }