private static HashSet <Type> GetKnownTypes(IEnumerable <Type> types, HashSet <Type> collection, TypeDiscoveryOptions options) { var foundTypes = collection ?? new HashSet <Type>(BuildInTypes); foreach (var knownType in types) { var genericArguments = Type.EmptyTypes; var type = knownType; var typeInfo = type.GetTypeInfo(); if (type.HasElementType) { type = type.GetElementType() ?? type; typeInfo = type.GetTypeInfo(); } if (typeInfo.IsGenericType) { genericArguments = typeInfo.GetGenericArguments(); type = type.GetGenericTypeDefinition() ?? type; } if (type.IsGenericParameter) { continue; } var alreadyAdded = foundTypes.Add(type) == false; if (typeInfo.IsGenericType && (options & TypeDiscoveryOptions.GenericArguments) != 0) { GetKnownTypes(genericArguments, foundTypes, options); } if (alreadyAdded) { continue; } if ((options & TypeDiscoveryOptions.Interfaces) != 0) { GetKnownTypes(typeInfo.GetImplementedInterfaces(), foundTypes, options); } if ((options & TypeDiscoveryOptions.KnownTypes) != 0) { GetKnownTypes(typeInfo.GetCustomAttributes(typeof(ExpressionKnownTypeAttribute), true).Cast <ExpressionKnownTypeAttribute>().Select(a => a.Type), foundTypes, options); } if ((options & TypeDiscoveryOptions.DeclaringTypes) != 0) { var declaringTypes = default(List <Type>); var declaringType = type.DeclaringType; // ReSharper disable HeuristicUnreachableCode // ReSharper disable ConditionIsAlwaysTrueOrFalse while (declaringType != null) { if (declaringTypes == null) { declaringTypes = new List <Type>(10); } declaringTypes.Add(declaringType); declaringType = declaringType.DeclaringType; } if (declaringTypes != null) { GetKnownTypes(declaringTypes, foundTypes, options); } // ReSharper restore ConditionIsAlwaysTrueOrFalse // ReSharper restore HeuristicUnreachableCode } } return(foundTypes); }
/// <summary> /// Creates new <see cref="KnownTypeResolver"/> from specified list of types and specified <see cref="TypeDiscoveryOptions"/>. /// </summary> /// <param name="knownTypes">List of known types.</param> /// <param name="otherTypeResolver">Backup type resolver used if current can't find a type.</param> /// <param name="options">Types discovery options.</param> public KnownTypeResolver(IEnumerable <Type> knownTypes, ITypeResolver otherTypeResolver, TypeDiscoveryOptions options) { if (knownTypes == null) { knownTypes = Type.EmptyTypes; } this.knownTypesByFullName = new Dictionary <string, List <Type> >(StringComparer.Ordinal); this.knownTypesByName = new Dictionary <string, List <Type> >(StringComparer.Ordinal); this.knownTypes = GetKnownTypes(knownTypes, null, options); foreach (var type in this.knownTypes) { foreach (var name in type.GetTypeNames()) { var typeList = default(List <Type>); if (this.knownTypesByName.TryGetValue(name, out typeList) == false) { this.knownTypesByName.Add(name, typeList = new List <Type>()); } typeList.Add(type); } foreach (var fullName in type.GetTypeFullNames()) { var typeList = default(List <Type>); if (this.knownTypesByFullName.TryGetValue(fullName, out typeList) == false) { this.knownTypesByFullName.Add(fullName, typeList = new List <Type>()); } typeList.Add(type); } } this.otherTypeResolver = otherTypeResolver; }