public static Func <object[], object> GetCreator(Type type, Type[] parameterTypes) { var key = new TypeKey(type, parameterTypes); var creator = creatorsByType.GetOrAdd(key, (keyArg) => { var typeDetail = TypeAnalyzer.GetTypeDetail(type); if (parameterTypes.Length == 0) { if (typeDetail.Creator == null) { return(null); } Func <object[], object> c = (a) => { return(typeDetail.Creator()); }; return(c); } foreach (var constructorDetail in typeDetail.ConstructorDetails) { if (constructorDetail.ParametersInfo.Count == parameterTypes.Length) { bool match = true; if (parameterTypes != null) { for (var i = 0; i < parameterTypes.Length; i++) { if (parameterTypes[i] != constructorDetail.ParametersInfo[i].ParameterType) { match = false; break; } } } if (match) { return(constructorDetail.Creator); } } } return(null); }); if (creator == null) { throw new MissingMethodException($"Constructor for {type.GetNiceName()} not available for the given parameters {String.Join(",", parameterTypes.Select(x => x.GetNiceName()))}"); } return(creator); }
private static void Generate() { var generationTypes = GetTypesFromAttribute(typeof(BaseGenerateAttribute)); foreach (var generationType in generationTypes) { var typeDetail = TypeAnalyzer.GetTypeDetail(generationType); foreach (var attribute in typeDetail.Attributes) { if (attribute is BaseGenerateAttribute generateAttribute) { var newType = generateAttribute.Generate(generationType); DiscoverType(newType); } } } }
internal TypeDetail(Type type) { this.Type = type; this.Interfaces = type.GetInterfaces(); var baseType = type; var baseTypes = new List <Type>(); while (baseType != null) { baseTypes.Add(baseType); baseType = baseType.BaseType; } this.BaseTypes = baseTypes; this.IsNullable = type.Name == nullaleTypeName; this.IsIEnumerable = !TypeLookup.CoreTypes.Contains(type) && (type.IsArray || type.Name == enumberableTypeName || Interfaces.Select(x => x.Name).Contains(enumberableTypeName)); this.IsICollection = !TypeLookup.CoreTypes.Contains(type) && (type.Name == collectionTypeName || Interfaces.Select(x => x.Name).Contains(collectionTypeName)); this.IsICollectionGeneric = !TypeLookup.CoreTypes.Contains(type) && (type.Name == collectionGenericTypeName || Interfaces.Select(x => x.Name).Contains(collectionGenericTypeName)); this.IsIList = !TypeLookup.CoreTypes.Contains(type) && (type.Name == listTypeName || type.Name == listGenericTypeName || Interfaces.Select(x => x.Name).Contains(listTypeName) || Interfaces.Select(x => x.Name).Contains(listGenericTypeName)); this.IsISet = !TypeLookup.CoreTypes.Contains(type) && (type.Name == setGenericTypeName || Interfaces.Select(x => x.Name).Contains(setGenericTypeName)); if (this.IsIEnumerable) { if (type.Name == enumberableGenericTypeName) { this.IsIEnumerableGeneric = true; this.IEnumerableGenericInnerType = type.GetGenericArguments()[0]; } else { var enumerableGeneric = Interfaces.Where(x => x.Name == enumberableGenericTypeName).ToArray(); if (enumerableGeneric.Length == 1) { this.IsIEnumerableGeneric = true; this.IEnumerableGenericInnerType = enumerableGeneric[0].GetGenericArguments()[0]; } } } if (type.IsGenericType) { this.InnerTypes = type.GetGenericArguments(); } else if (type.IsArray) { this.InnerTypes = new Type[] { type.GetElementType() } } ; else { this.InnerTypes = Type.EmptyTypes; } if (TypeLookup.CoreTypeLookup(type, out CoreType coreTypeLookup)) { this.CoreType = coreTypeLookup; } if (TypeLookup.SpecialTypeLookup(type, out SpecialType specialTypeLookup)) { this.SpecialType = specialTypeLookup; switch (specialTypeLookup) { case Reflection.SpecialType.Task: this.IsTask = true; break; case Reflection.SpecialType.Dictionary: var innerType = TypeAnalyzer.GetGenericType(keyValuePairType, (Type[])this.InnerTypes); this.InnerTypes = new Type[] { innerType }; break; } } if (type.IsEnum) { var enumEnderlyingType = Enum.GetUnderlyingType(this.Type); if (!TypeLookup.CoreTypeLookup(enumEnderlyingType, out CoreType enumCoreTypeLookup)) { throw new NotImplementedException("Should not happen"); } this.EnumUnderlyingType = enumCoreTypeLookup; } else if (this.IsNullable && this.InnerTypes[0].IsEnum) { var enumEnderlyingType = Enum.GetUnderlyingType(this.InnerTypes[0]); if (!TypeLookup.CoreTypeLookup(enumEnderlyingType, out CoreType enumCoreTypeLookup)) { throw new NotImplementedException("Should not happen"); } enumCoreTypeLookup = enumCoreTypeLookup switch { Reflection.CoreType.Byte => Reflection.CoreType.ByteNullable, Reflection.CoreType.SByte => Reflection.CoreType.SByteNullable, Reflection.CoreType.Int16 => Reflection.CoreType.Int16Nullable, Reflection.CoreType.UInt16 => Reflection.CoreType.UInt16Nullable, Reflection.CoreType.Int32 => Reflection.CoreType.Int32Nullable, Reflection.CoreType.UInt32 => Reflection.CoreType.UInt32Nullable, Reflection.CoreType.Int64 => Reflection.CoreType.Int64Nullable, Reflection.CoreType.UInt64 => Reflection.CoreType.UInt64Nullable, _ => throw new NotImplementedException(), }; this.EnumUnderlyingType = enumCoreTypeLookup; } this.IsGraphLocalProperty = this.CoreType.HasValue || this.EnumUnderlyingType.HasValue || this.SpecialType.HasValue || this.Type.IsArray || (this.IsNullable && this.InnerTypes[0].IsArray); var methodDetails = new List <MethodDetail>(); if (!type.IsGenericTypeDefinition) { var methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); foreach (var method in methods) { methodDetails.Add(new MethodDetail(method)); } if (type.IsInterface) { foreach (var i in Interfaces) { var iMethods = i.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); foreach (var method in iMethods) { methodDetails.Add(new MethodDetail(method)); } } } } this.MethodDetails = methodDetails.ToArray(); var constructorDetails = new List <ConstructorDetails>(); if (!type.IsGenericTypeDefinition) { var constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var constructor in constructors) { constructorDetails.Add(new ConstructorDetails(constructor)); } } this.ConstructorDetails = constructorDetails.ToArray(); if (!type.IsAbstract && !type.IsGenericTypeDefinition) { var emptyConstructor = this.ConstructorDetails.FirstOrDefault(x => x.ParametersInfo.Count == 0); if (emptyConstructor != null) { this.Creator = () => { return(emptyConstructor.Creator(null)); }; } else if (type.IsValueType && type.Name != "Void") { var constantExpression = Expression.Convert(Expression.Default(type), typeof(object)); var lambda = Expression.Lambda <Func <object> >(constantExpression).Compile(); this.Creator = lambda; } else if (type == typeof(string)) { this.Creator = () => { return(String.Empty); }; } } var test = type.Name; this.Attributes = type.GetCustomAttributes().ToArray(); if (!this.CoreType.HasValue) { var typeMembers = new List <MemberDetail>(); if (!type.IsGenericTypeDefinition) { var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (type.IsInterface) { foreach (var i in Interfaces) { var iProperties = i.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var iFields = i.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); properties = properties.Concat(iProperties.Where(x => !properties.Select(y => y.Name).Contains(x.Name))).ToArray(); fields = fields.Concat(iFields.Where(x => !fields.Select(y => y.Name).Contains(x.Name))).ToArray(); } } foreach (var property in properties) { if (property.GetIndexParameters().Length > 0) { continue; } MemberDetail backingMember = null; var backingField = fields.FirstOrDefault(x => x.Name == $"<{property.Name}>k__BackingField"); if (backingField != null) { backingMember = new MemberDetail(backingField, null); } typeMembers.Add(new MemberDetail(property, backingMember)); } foreach (var field in fields.Where(x => !x.Name.EndsWith("k__BackingField"))) { typeMembers.Add(new MemberDetail(field, null)); } } this.MemberDetails = typeMembers.ToArray(); this.membersByName = this.MemberDetails.ToDictionary(x => x.Name); } else { var typeMembers = Array.Empty <MemberDetail>(); this.MemberDetails = typeMembers; this.membersByName = this.MemberDetails.ToDictionary(x => x.Name); } if (this.IsTask && this.Type.IsGenericType) { if (this.membersByName.TryGetValue("Result", out MemberDetail resultMember)) { this.TaskResultGetter = resultMember.Getter; } } }