Exemple #1
0
        public static Type MakeGenericType(Type baseType, Type[] types)
        {
            // emulate Nullable<T>
            if (baseType == typeof(Nullable <>))
            {
                if (types.Length != 1)
                {
                    ThrowHelper.ThrowArgumentException(ExceptionResource.WrongNumberOfArguments);
                }

                var ret = NullableReflection.GetNullableTFromUnterlyingType(types[0]);

                if (ret != null)
                {
                    return(ret);
                }

                // can't create a nullable instance of non-predifined nullable,
                // because of all the compiler-voodoo around Nullables.
                return(null);
            }

            var expected = GetGenericArgumentCount(baseType);

            if (types.Length != expected)
            {
                throw new ArgumentOutOfRangeException("types", string.Format("exected {0} generic arguments, got {1} for type {2}", expected, types.Length, baseType.FullName));
            }

            return(GenericInstanceFactory.GetOrMakeGenericInstanceType(baseType, types));
        }
Exemple #2
0
        public static Type GetReflectionSafeType(Type type, object obj)
        {
            if (!(obj is IGenericTypeDefinition)) // fast path
            {
                return(type);
            }

            // Note: If java had ephemerons, we could cache the return value.
            //       Without ephemerons, this doesn't seem to be a good idea.
            //       We could though create an extra field in each generic type
            //       to hold the cached value. This would only pay off if
            //       GetTypeReflectionSafe is actually called multiple times
            //       on the same object.
            var info = GetOrCreateGenericsInfo(type);

            Field[] genericsFields = info.GenericInstanceFields;

            int length;

            if (genericsFields == null || (length = genericsFields.Length) == 0)
            {
                return(type);
            }

            Type[] genericParameters;

            if (info.GenericInstanceFieldIsTypeArray)
            {
                genericParameters = (Type[])genericsFields[0].Get(obj);
                return(GenericInstanceFactory.GetOrMakeGenericInstanceType(type, genericParameters));
            }
            if (length > 4)
            {
                // This can not happen with the current compiler.
                genericParameters = genericsFields.Select(f => (Type)f.Get(obj));
                return(GenericInstanceFactory.GetOrMakeGenericInstanceType(type, genericParameters));
            }

            Type p1 = (Type)genericsFields[0].Get(obj);
            Type p2 = null, p3 = null, p4 = null;

            if (length > 1)
            {
                p2 = (Type)genericsFields[1].Get(obj);
                if (length > 2)
                {
                    p3 = (Type)genericsFields[2].Get(obj);
                    if (length > 3)
                    {
                        p4 = (Type)genericsFields[3].Get(obj);
                    }
                }
            }
            return(GenericInstanceFactory.GetOrMakeGenericInstanceType(type, p1, p2, p3, p4));
        }
Exemple #3
0
        public static Type ToGenericInstanceType(Type perceivedType, Type parentType, GenericDefinition m)
        {
            // is a specialized type defined?
            var genericInstanceType = m.GenericInstanceType;

            if (genericInstanceType != null)
            {
                return(genericInstanceType);
            }

            int genericParameter = -1;
            var genericArguments = m.GenericArguments;

            // is a generic type definition class defined?
            var genericTypeDef = m.GenericTypeDefinition;

            if (genericTypeDef == null)
            {
                genericTypeDef   = perceivedType;
                genericParameter = m.GenericParameter;
            }

            // retrieve generic parameters if required.
            GenericTypeInfo parentGenericArguments     = null;
            bool            needParentGenericArguments = genericParameter >= 0 ||
                                                         genericArguments.Any(a => a.FixedType == null);

            if (needParentGenericArguments)
            {
                parentGenericArguments = GenericInstanceFactory.GetGenericTypeInfo(parentType);

                if (parentGenericArguments == null)
                {
                    // Can either happen when the generics reflection annotations where not preserved
                    // (i.e. a bug),  when the user did not call GetTypeReflectionSafe() on an object,
                    // or when requesting generics info not for an instance type, e.g. typeof(List<>).
                    // As the second case can be difficult to debug, we emit a warning. TODO: we should
                    // probably not emit a warning when the user code runs in release mode.
                    Log.W("dot42", string.Format("Unable to reconstruct generic type definition for type {0}, parent type {1}. Did you use obj.GetTypeReflectionSafe()? If you are reflecting on an open generic type, i.e. typeof(List<>) you can ignore this warning.", perceivedType.FullName, parentType.FullName));
                    return(genericTypeDef);
                }
            }


            if (genericParameter != -1)
            {
                // ReSharper disable once PossibleNullReferenceException
                genericTypeDef = parentGenericArguments.GetGenericParameter(genericParameter);
            }

            if (genericArguments != null && genericArguments.Length > 0)
            {
                Type[] genericParameters = new Type[genericArguments.Length];

                for (int i = 0; i < genericArguments.Length; ++i)
                {
                    Type resolvedArg;
                    var  arg = genericArguments[i];
                    if (arg.NestedType != null)
                    {
                        resolvedArg = ToGenericInstanceType(typeof(object), parentType, arg.NestedType);
                    }
                    else if (arg.FixedType != null)
                    {
                        resolvedArg = arg.FixedType;
                    }
                    else
                    {
                        // must be an index
                        // ReSharper disable once PossibleNullReferenceException
                        resolvedArg = parentGenericArguments.GetGenericParameter(arg.ContainingTypeArgumentIndex);
                    }

                    genericParameters[i] = resolvedArg;
                }

                return(GenericInstanceFactory.GetOrMakeGenericInstanceType(genericTypeDef, genericParameters));
            }

            // return the type.
            return(genericTypeDef);
        }