예제 #1
0
        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);
        }
예제 #2
0
        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}"),
                });
예제 #3
0
        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;
                }
            }
        }