示例#1
0
        /// <summary>
        /// Replace some of the types in a type's construction with a new set of types. This function does not
        /// support any situation where there is an instantiated generic that is not represented by an
        /// InstantiatedType. Does not replace the open generics that may be instantiated over in this type.
        ///
        /// For instance, Given MyType&lt;object, int[]&gt;,
        ///  an array of types to replace such as {int,object}, and
        ///  an array of replacement types such as {string,__Canon}.
        ///  The result shall be MyType&lt;__Canon, string[]&gt;
        ///
        /// This function cannot be used to replace MyType in the above example.
        /// </summary>
        public static TypeDesc ReplaceTypesInConstructionOfType(this TypeDesc type, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes)
        {
            int directReplacementIndex = Array.IndexOf(typesToReplace, type);

            if (directReplacementIndex != -1)
            {
                return(replacementTypes[directReplacementIndex]);
            }

            if (type.HasInstantiation)
            {
                TypeDesc[] newInstantiation = null;
                Debug.Assert(type is InstantiatedType);
                int instantiationIndex = 0;
                for (; instantiationIndex < type.Instantiation.Length; instantiationIndex++)
                {
                    TypeDesc oldType = type.Instantiation[instantiationIndex];
                    TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                    if ((oldType != newType) || (newInstantiation != null))
                    {
                        if (newInstantiation == null)
                        {
                            newInstantiation = new TypeDesc[type.Instantiation.Length];
                            for (int i = 0; i < instantiationIndex; i++)
                            {
                                newInstantiation[i] = type.Instantiation[i];
                            }
                        }
                        newInstantiation[instantiationIndex] = newType;
                    }
                }
                if (newInstantiation != null)
                {
                    return(type.Context.GetInstantiatedType((MetadataType)type.GetTypeDefinition(), new Instantiation(newInstantiation)));
                }
            }
            else if (type.IsParameterizedType)
            {
                ParameterizedType parameterizedType = (ParameterizedType)type;
                TypeDesc          oldParameter      = parameterizedType.ParameterType;
                TypeDesc          newParameter      = oldParameter.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                if (oldParameter != newParameter)
                {
                    if (type.IsArray)
                    {
                        ArrayType arrayType = (ArrayType)type;
                        if (arrayType.IsSzArray)
                        {
                            return(type.Context.GetArrayType(newParameter));
                        }
                        else
                        {
                            return(type.Context.GetArrayType(newParameter, arrayType.Rank));
                        }
                    }
                    else if (type.IsPointer)
                    {
                        return(type.Context.GetPointerType(newParameter));
                    }
                    else if (type.IsByRef)
                    {
                        return(type.Context.GetByRefType(newParameter));
                    }
                    Debug.Fail("Unknown form of type");
                }
            }
            else if (type.IsFunctionPointer)
            {
                MethodSignature        oldSig     = ((FunctionPointerType)type).Signature;
                MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(oldSig);
                sigBuilder.ReturnType = oldSig.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                for (int paramIndex = 0; paramIndex < oldSig.Length; paramIndex++)
                {
                    sigBuilder[paramIndex] = oldSig[paramIndex].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                }

                MethodSignature newSig = sigBuilder.ToSignature();
                if (newSig != oldSig)
                {
                    return(type.Context.GetFunctionPointerType(newSig));
                }
            }

            return(type);
        }
示例#2
0
        /// <summary>
        /// Replace some of the types in a method's construction with a new set of types.
        /// Does not replace the open generics that may be instantiated over in this type.
        ///
        /// For instance, Given MyType&lt;object, int[]&gt;.Function&lt;short&gt;(),
        ///  an array of types to replace such as {int,short}, and
        ///  an array of replacement types such as {string,char}.
        ///  The result shall be MyType&lt;object, string[]&gt;.Function&lt;char&gt;
        ///
        /// This function cannot be used to replace MyType in the above example.
        /// </summary>
        public static MethodDesc ReplaceTypesInConstructionOfMethod(this MethodDesc method, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes)
        {
            TypeDesc   newOwningType      = method.OwningType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
            MethodDesc methodOnOwningType = null;
            bool       owningTypeChanged  = false;

            if (newOwningType == method.OwningType)
            {
                methodOnOwningType = method.GetMethodDefinition();
            }
            else
            {
                methodOnOwningType = TypeSystemHelpers.FindMethodOnExactTypeWithMatchingTypicalMethod(newOwningType, method);
                owningTypeChanged  = true;
            }

            MethodDesc result;

            if (!method.HasInstantiation)
            {
                result = methodOnOwningType;
            }
            else
            {
                Debug.Assert(method is InstantiatedMethod);

                TypeDesc[] newInstantiation   = null;
                int        instantiationIndex = 0;
                for (; instantiationIndex < method.Instantiation.Length; instantiationIndex++)
                {
                    TypeDesc oldType = method.Instantiation[instantiationIndex];
                    TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                    if ((oldType != newType) || (newInstantiation != null))
                    {
                        if (newInstantiation == null)
                        {
                            newInstantiation = new TypeDesc[method.Instantiation.Length];
                            for (int i = 0; i < instantiationIndex; i++)
                            {
                                newInstantiation[i] = method.Instantiation[i];
                            }
                        }
                        newInstantiation[instantiationIndex] = newType;
                    }
                }

                if (newInstantiation != null)
                {
                    result = method.Context.GetInstantiatedMethod(methodOnOwningType, new Instantiation(newInstantiation));
                }
                else if (owningTypeChanged)
                {
                    result = method.Context.GetInstantiatedMethod(methodOnOwningType, method.Instantiation);
                }
                else
                {
                    result = method;
                }
            }

            return(result);
        }