/// <summary> /// Create a new type support /// </summary> /// <param name="type">The type to analyze</param> /// <param name="options">The type support inspection options</param> public ExtendedType(Type type, TypeSupportOptions options) { Type = type ?? throw new ArgumentNullException(); Attributes = new List <Type>(); Interfaces = new List <Type>(); GenericArgumentTypes = new List <Type>(); KnownConcreteTypes = new List <Type>(); EnumValues = new List <KeyValuePair <object, string> >(); Properties = new List <ExtendedProperty>(); Fields = new List <ExtendedField>(); Constructors = new List <ConstructorInfo>(); EmptyConstructors = new List <ConstructorInfo>(); var isCachingSupported = options.BitwiseHasFlag(TypeSupportOptions.Caching); // if the type is cached, use it if (isCachingSupported && ExtendedTypeCache.Contains(type, options)) { InitializeFromCache(ExtendedTypeCache.Get(type, options)); } else { // inspect the type with the given options var typeInspector = new TypeInspector(this, options); typeInspector.Inspect(); if (isCachingSupported) { ExtendedTypeCache.CacheType(this, options); } } }
/// <summary> /// Returns true if the extended type is cached /// </summary> /// <param name="type">The type to lookup</param> /// <param name="options">The options for the extended type</param> /// <returns></returns> public static bool Contains(Type type, TypeSupportOptions options) { _cacheLock.Wait(); try { return(ContainsInternal(type, options)); } finally { _cacheLock.Release(); } }
/// <summary> /// Get an extended type from the cache /// </summary> /// <param name="type">The type to lookup</param> /// <param name="options">The options for the extended type</param> /// <returns></returns> public static ExtendedType Get(Type type, TypeSupportOptions options) { _cacheLock.Wait(); try { if (!ContainsInternal(type, options)) { throw new InvalidOperationException($"Requested type '{type.Name}' is not cached"); } var key = GenerateKey(type, options); return(Instance.CachedTypes[key]); } finally { _cacheLock.Release(); } }
/// <summary> /// Generates the type of key to use for the type cache /// </summary> /// <param name="type">The type to lookup</param> /// <param name="options">The options for the extended type</param> /// <returns></returns> private static CacheKey GenerateKey(Type type, TypeSupportOptions options) { if (options != TypeSupportOptions.All) { // does it exist with all options available? var allKey = new CacheKey(type, TypeSupportOptions.All); var containsAllKey = Instance.CachedTypes.ContainsKey(allKey); if (containsAllKey) { return(allKey); } } // use the key as-is var key = new CacheKey(type, options); return(key); }
private void InspectGenericType(ExtendedType extendedType, Type type, TypeSupportOptions options) { var genericTypeDefinition = type.GetGenericTypeDefinition(); var args = type.GetGenericArguments(); if (args?.Any() == true) { foreach (var arg in args) { extendedType.GenericArgumentTypes.Add(arg); } } if (options.BitwiseHasFlag(TypeSupportOptions.Collections)) { if (typeof(ICollection).IsAssignableFrom(genericTypeDefinition) || typeof(IList) == type || typeof(IList).IsAssignableFrom(genericTypeDefinition) || typeof(IList <>).IsAssignableFrom(genericTypeDefinition) || typeof(ICollection <>).IsAssignableFrom(genericTypeDefinition) || typeof(Collection <>).IsAssignableFrom(genericTypeDefinition) ) { extendedType.IsCollection = true; extendedType.ElementType = args.FirstOrDefault(); if (extendedType.ElementType != null) { extendedType.ElementNullableBaseType = GetNullableBaseType(extendedType.ElementType); } } if (genericTypeDefinition == typeof(Dictionary <,>) || genericTypeDefinition == typeof(ConcurrentDictionary <,>) || genericTypeDefinition == typeof(IDictionary <,>)) { extendedType.IsDictionary = true; } } if (genericTypeDefinition == typeof(KeyValuePair <,>)) { extendedType.IsKeyValuePair = true; extendedType.ElementType = args.FirstOrDefault(); } }
/// <summary> /// Cache an extended type /// </summary> /// <param name="type">The extended type to cache</param> /// <param name="options">The options for the extended type</param> public static void CacheType(ExtendedType type, TypeSupportOptions options) { _cacheLock.Wait(); try { var key = GenerateKey(type.Type, options); if (!Instance.CachedTypes.ContainsKey(key)) { Instance.CachedTypes.Add(key, type); if (key.Options == TypeSupportOptions.All) { // remove any types with options less than all RemoveLowerOptions(type.Type); } } } finally { _cacheLock.Release(); } }
/// <summary> /// Get the extended type for a Type /// </summary> /// <param name="type"></param> /// <param name="options">The type support inspection options</param> /// <returns></returns> public static ExtendedType GetExtendedType(this object type, TypeSupportOptions options) { return(new ExtendedType(type.GetType(), options)); }
/// <summary> /// Get the extended type for a Type /// </summary> /// <param name="type"></param> /// <param name="options">The type support inspection options</param> /// <returns></returns> public static ExtendedType GetExtendedType(this Type type, TypeSupportOptions options) { return(new ExtendedType(type, options)); }
public CacheKey(Type type, TypeSupportOptions options) { Type = type; Options = options; }
/// <summary> /// Create a new type support /// </summary> /// <param name="assemblyQualifiedFullName">The full name of the type to create, <see cref="Type.AssemblyQualifiedName"/></param> /// <param name="options">The type support inspection options</param> public ExtendedType(string assemblyQualifiedFullName, TypeSupportOptions options) : this(Type.GetType(assemblyQualifiedFullName), options) { }
/// <summary> /// Inspects a type /// </summary> /// <param name="extendedType">The extended type to inspect</param> /// <param name="options">The options to use for inspection</param> internal TypeInspector(ExtendedType extendedType, TypeSupportOptions options) { _extendedType = extendedType; _options = options; }