public TypeInstantiation(TypeInstantiationInfo instantiationInfo, TypeInstantiationContext instantiationContext) : base( ArgumentUtility.CheckNotNull("instantiationInfo", instantiationInfo).GenericTypeDefinition.Name, instantiationInfo.GenericTypeDefinition.Namespace, instantiationInfo.GenericTypeDefinition.Attributes, genericTypeDefinition: instantiationInfo.GenericTypeDefinition, typeArguments: instantiationInfo.TypeArguments) { ArgumentUtility.CheckNotNull("instantiationContext", instantiationContext); _instantiationInfo = instantiationInfo; _instantiationContext = instantiationContext; var genericTypeDefinition = instantiationInfo.GenericTypeDefinition; var declaringType = genericTypeDefinition.DeclaringType; // Even though the _genericTypeDefinition includes the type parameters of the enclosing type(s) (if any), declaringType.GetGenericArguments() // will return objects not equal to this type's generic parameters. Since the call to SetDeclaringType below needs to replace the those type // parameters with type arguments, add a mapping for the declaring type's generic parameters in addition to this type's generic parameters. // ReSharper disable ConditionIsAlwaysTrueOrFalse // ReSharper is wrong here, declaringType can be null. var outerMapping = declaringType != null ? declaringType.GetGenericArguments().Zip(instantiationInfo.TypeArguments, Tuple.Create) : new Tuple <Type, Type> [0]; // ReSharper restore ConditionIsAlwaysTrueOrFalse var mapping = genericTypeDefinition.GetGenericArguments().Zip(instantiationInfo.TypeArguments, Tuple.Create); _parametersToArguments = outerMapping.Concat(mapping).ToDictionary(t => t.Item1, t => t.Item2); // Add own instantation to context before substituting any generic parameters. instantiationContext.Add(instantiationInfo, this); // ReSharper disable ConditionIsAlwaysTrueOrFalse // ReSharper is wrong here, declaringType can be null. if (declaringType != null) { SetDeclaringType(SubstituteGenericParameters(declaringType)); } // ReSharper restore ConditionIsAlwaysTrueOrFalse if (genericTypeDefinition.BaseType != null) { SetBaseType(SubstituteGenericParameters(genericTypeDefinition.BaseType)); } _nestedTypes = new Lazy <IReadOnlyCollection <Type> > (() => CreateNestedType().ToList().AsReadOnly()); _interfaces = new Lazy <IReadOnlyCollection <Type> > (() => CreateInterfaces().ToList().AsReadOnly()); _fields = new Lazy <IReadOnlyCollection <FieldInfo> > (() => CreateFields().Cast <FieldInfo>().ToList().AsReadOnly()); _constructors = new Lazy <IReadOnlyCollection <ConstructorInfo> > (() => CreateConstructors().Cast <ConstructorInfo>().ToList().AsReadOnly()); _methods = new Lazy <IReadOnlyCollection <MethodOnTypeInstantiation> > (() => CreateMethods().ToList().AsReadOnly()); _properties = new Lazy <IReadOnlyCollection <PropertyInfo> > (() => CreateProperties().Cast <PropertyInfo>().ToList().AsReadOnly()); _events = new Lazy <IReadOnlyCollection <EventInfo> > (() => CreateEvents().Cast <EventInfo>().ToList().AsReadOnly()); }
public Type Instantiate(TypeInstantiationInfo instantiationInfo) { ArgumentUtility.CheckNotNull("instantiationInfo", instantiationInfo); TypeInstantiation typeInstantiation; if (_instantiations.TryGetValue(instantiationInfo, out typeInstantiation)) { return(typeInstantiation); } var genTypeDef = instantiationInfo.GenericTypeDefinition; var typeArgs = instantiationInfo.TypeArguments; if (genTypeDef.IsRuntimeType() && typeArgs.All(a => a.IsRuntimeType())) { return(genTypeDef.MakeGenericType(typeArgs.ToArray())); } return(new TypeInstantiation(instantiationInfo, this)); }
public Type SubstituteGenericParameters(Type type, IDictionary <Type, Type> parametersToArguments) { ArgumentUtility.CheckNotNull("type", type); ArgumentUtility.CheckNotNull("parametersToArguments", parametersToArguments); Type typeArgument; if (parametersToArguments.TryGetValue(type, out typeArgument)) { return(Assertion.IsNotNull(typeArgument, "Type-argument for type-parameter '{0}' was null.", type)); } if (type.IsArray) { return(SubstituteArrayElementType(type, parametersToArguments)); } if (type.IsByRef) { return(SubstituteByRefElementType(type, parametersToArguments)); } if (!type.IsGenericType) { return(type); } var oldTypeArguments = type.GetGenericArguments(); var newTypeArguments = oldTypeArguments.Select(t => SubstituteGenericParameters(t, parametersToArguments)).ToList(); // No substitution necessary (this is an optimization only). if (oldTypeArguments.SequenceEqual(newTypeArguments)) { return(type); } var genericTypeDefinition = type.GetGenericTypeDefinition(); var instantiationInfo = new TypeInstantiationInfo(genericTypeDefinition, newTypeArguments); return(Instantiate(instantiationInfo)); }