private static void EmitDefault(ILGenerator il, Type type) { if (TypeLookup.CoreTypeLookup(type, out CoreType coreType)) { switch (coreType) { case CoreType.Boolean: case CoreType.Byte: case CoreType.SByte: case CoreType.Int16: case CoreType.UInt16: case CoreType.Int32: case CoreType.UInt32: il.Emit(OpCodes.Ldc_I4, 0); return; case CoreType.Int64: case CoreType.UInt64: il.Emit(OpCodes.Ldc_I4, 0); il.Emit(OpCodes.Conv_I8); return; case CoreType.Single: il.Emit(OpCodes.Ldc_R4, 0f); return; case CoreType.Double: il.Emit(OpCodes.Ldc_R8, 0d); return; case CoreType.Decimal: il.Emit(OpCodes.Ldc_I4, 0); return; case CoreType.Char: il.Emit(OpCodes.Ldc_I4, 0); return; case CoreType.DateTime: case CoreType.DateTimeOffset: case CoreType.TimeSpan: case CoreType.Guid: il.DeclareLocal(type); il.DeclareLocal(type); il.Emit(OpCodes.Ldloca_S, 0); il.Emit(OpCodes.Initobj, type); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldloc_1); return; case CoreType.String: default: il.Emit(OpCodes.Ldnull); return; } } il.Emit(OpCodes.Ldnull); }
public static object Convert(object obj, Type type) { if (!TypeLookup.CoreTypeLookup(type, out CoreType coreType)) { throw new NotImplementedException($"Type convert not available for {type.Name}"); } if (obj == null) { return(coreType switch { CoreType.Boolean => default(bool), CoreType.Byte => default(byte), CoreType.SByte => default(sbyte), CoreType.UInt16 => default(ushort), CoreType.Int16 => default(short), CoreType.UInt32 => default(uint), CoreType.Int32 => default(int), CoreType.UInt64 => default(ulong), CoreType.Int64 => default(long), CoreType.Single => default(float), CoreType.Double => default(double), CoreType.Decimal => default(decimal), CoreType.Char => default(char), CoreType.DateTime => default(DateTime), CoreType.DateTimeOffset => default(DateTimeOffset), CoreType.TimeSpan => default(TimeSpan), CoreType.Guid => default(Guid), CoreType.String => default(string), CoreType.BooleanNullable => null, CoreType.ByteNullable => null, CoreType.SByteNullable => null, CoreType.UInt16Nullable => null, CoreType.Int16Nullable => null, CoreType.UInt32Nullable => null, CoreType.Int32Nullable => null, CoreType.UInt64Nullable => null, CoreType.Int64Nullable => null, CoreType.SingleNullable => null, CoreType.DoubleNullable => null, CoreType.DecimalNullable => null, CoreType.CharNullable => null, CoreType.DateTimeNullable => null, CoreType.DateTimeOffsetNullable => null, CoreType.TimeSpanNullable => null, CoreType.GuidNullable => null, _ => throw new NotImplementedException($"Type conversion not available for {type.Name}"), });
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; } } }