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)); }
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)); }
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); }