예제 #1
0
        /// <summary>
        /// Transform open generic types to closed instantiation using context information.
        /// As an example, if B{T} inherits from A{T}, running it with B{C} as context and A{B.T} as type, ti will return A{C}.
        /// </summary>
        public static TypeReference Process(TypeReference context, TypeReference type)
        {
            if (type == null)
            {
                return(null);
            }

            var genericInstanceTypeContext = context as GenericInstanceType;

            if (genericInstanceTypeContext == null)
            {
                return(type);
            }

            // Build dictionary that will map generic type to their real implementation type
            var resolvedType       = genericInstanceTypeContext.ElementType;
            var genericTypeMapping = new Dictionary <TypeReference, TypeReference>();

            for (int i = 0; i < resolvedType.GenericParameters.Count; ++i)
            {
                var genericParameter = genericInstanceTypeContext.ElementType.GenericParameters[i];
                genericTypeMapping.Add(genericParameter, genericInstanceTypeContext.GenericArguments[i]);
            }

            var visitor = new ResolveGenericsVisitor(genericTypeMapping);
            var result  = visitor.VisitDynamic(type);

            // Make sure type is closed now
            if (result.ContainsGenericParameter())
            {
                throw new InvalidOperationException("Unsupported generic resolution.");
            }

            return(result);
        }
예제 #2
0
        public static void MethodSignatureMangledName(this MethodReference method, StringBuilder builder)
        {
            builder.Append("(");
            if (method.HasParameters)
            {
                var parameters = method.Parameters;
                for (int i = 0; i < parameters.Count; i++)
                {
                    ParameterDefinition parameter = parameters[i];
                    if (i > 0)
                    {
                        builder.Append(",");
                    }
                    if (parameter.ParameterType.IsSentinel)
                    {
                        builder.Append("...,");
                    }

                    // We are replacing GenericInstance of type !0 with their real definitions (T, U, etc...)
                    var parameterType = ResolveGenericsVisitor.Process(method, parameter.ParameterType, true);
                    builder.Append(parameterType.MangledName());
                }
            }
            builder.Append(")");
        }
예제 #3
0
        public static TypeReference Process(MethodReference context, TypeReference type, bool resolveOnlyReferences = false)
        {
            if (type == null)
            {
                return(null);
            }

            if (context == null)
            {
                return(type);
            }

            // Visit recursively and replace generic parameters with generic arguments from context
            var genericInstanceTypeContext   = context.DeclaringType as GenericInstanceType;
            var genericInstanceMethodContext = context as GenericInstanceMethod;

            if (genericInstanceMethodContext == null && genericInstanceTypeContext == null)
            {
                return(type);
            }

            var visitor = new ResolveGenericsVisitor(context, resolveOnlyReferences);
            var result  = visitor.VisitDynamic(type);

            return(result);
        }
예제 #4
0
        /// <summary>
        /// Transform open generic types to closed instantiation using context information.
        /// As an example, if B{T} inherits from A{T}, running it with B{C} as context and A{B.T} as type, ti will return A{C}.
        /// </summary>
        public static TypeReference Process(TypeReference context, TypeReference type)
        {
            if (type == null)
            {
                return(null);
            }

            var genericInstanceTypeContext = context as GenericInstanceType;

            if (genericInstanceTypeContext == null)
            {
                return(type);
            }

            // Visit recursively and replace generic parameters with generic arguments from context
            var visitor = new ResolveGenericsVisitor(context);
            var result  = visitor.VisitDynamic(type);

            // Make sure type is closed now
            if (result.ContainsGenericParameter)
            {
                throw new InvalidOperationException("Unsupported generic resolution.");
            }

            return(result);
        }
예제 #5
0
        public static TypeReference Process(MethodReference context, TypeReference type)
        {
            if (type == null)
            {
                return(null);
            }

            if (context == null)
            {
                return(type);
            }

            var genericInstanceTypeContext   = context.DeclaringType as GenericInstanceType;
            var genericInstanceMethodContext = context as GenericInstanceMethod;

            if (genericInstanceMethodContext == null && genericInstanceTypeContext == null)
            {
                return(type);
            }

            // Build dictionary that will map generic type to their real implementation type
            var genericTypeMapping = new Dictionary <TypeReference, TypeReference>(TypeReferenceComparer.Default);

            if (genericInstanceTypeContext != null)
            {
                var resolvedType = genericInstanceTypeContext.ElementType;
                for (int i = 0; i < resolvedType.GenericParameters.Count; ++i)
                {
                    var genericParameter = genericInstanceTypeContext.ElementType.GenericParameters[i];
                    genericTypeMapping.Add(genericParameter, genericInstanceTypeContext.GenericArguments[i]);
                }
            }

            if (genericInstanceMethodContext != null)
            {
                var elementMethod  = genericInstanceMethodContext.ElementMethod;
                var resolvedMethod = genericInstanceMethodContext.Resolve();
                for (int i = 0; i < elementMethod.GenericParameters.Count; ++i)
                {
                    var genericParameter = elementMethod.GenericParameters[i];
                    genericTypeMapping.Add(genericParameter, genericInstanceMethodContext.GenericArguments[i]);

                    var genericParameter2 = resolvedMethod.GenericParameters[i];
                    if (genericParameter != genericParameter2)
                    {
                        genericTypeMapping.Add(genericParameter2, genericInstanceMethodContext.GenericArguments[i]);
                    }
                }
            }

            var visitor = new ResolveGenericsVisitor(genericTypeMapping);
            var result  = visitor.VisitDynamic(type);

            // Make sure type is closed now
            //if (result.ContainsGenericParameter())
            //    throw new InvalidOperationException("Unsupported generic resolution.");

            return(result);
        }
예제 #6
0
        static bool MethodMatch(MethodReference candidate, MethodReference method)
        {
            var candidateResolved = candidate.Resolve();

            // Check overrides
            if (candidateResolved.HasOverrides)
            {
                foreach (var @override in candidateResolved.Overrides)
                {
                    var resolvedOverride = ResolveGenericsVisitor.Process(candidate, @override);
                    if (resolvedOverride.FullName == method.FullName)
                    {
                        return(true);
                    }
                }
            }

            if (!candidateResolved.IsVirtual)
            {
                return(false);
            }

            if (candidate.Name != method.Name)
            {
                return(false);
            }

            if (!TypeMatch(ResolveGenericsVisitor.Process(candidate, candidate.ReturnType), ResolveGenericsVisitor.Process(method, method.ReturnType)))
            {
                return(false);
            }

            if (candidate.Parameters.Count != method.Parameters.Count)
            {
                return(false);
            }

            for (int i = 0; i < candidate.Parameters.Count; i++)
            {
                if (!TypeMatch(ResolveGenericsVisitor.Process(candidate, candidate.Parameters[i].ParameterType), ResolveGenericsVisitor.Process(method, method.Parameters[i].ParameterType)))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #7
0
        public static string MangledName(this MethodReference method)
        {
            var builder = new StringBuilder();

            if (method.DeclaringType != null)
            {
                builder.Append(method.DeclaringType.MangledName()).Append("::");
            }
            builder.Append(method.Name);

            // Append generic arguments
            var genericInstanceMethod = method as GenericInstanceMethod;

            if (genericInstanceMethod != null)
            {
                foreach (var genericArgument in genericInstanceMethod.GenericArguments)
                {
                    builder.Append('_');
                    builder.Append(genericArgument.MangledName());
                }
            }

            if (method.Name == "op_Implicit" || method.Name == "op_Explicit")
            {
                // If it's op_Implicit or op_Explicit, we might want to use return type instead of first parameter (depending on which way the conversion is)
                builder.Append("_");
                if (MemberEqualityComparer.Default.Equals(method.Parameters[0].ParameterType, method.DeclaringType))
                {
                    builder.Append("ret_");
                    builder.Append(method.ReturnType.MangledName());
                }
                else
                {
                    builder.Append(ResolveGenericsVisitor.Process(method, method.Parameters[0].ParameterType).MangledName());
                }
            }
            else
            {
                // Method signature
                MethodSignatureMangledName(method, builder);
            }

            return(builder.ToString());
        }
예제 #8
0
        public static TypeReference Process(MethodReference context, TypeReference type, bool resolveOnlyReferences = false)
        {
            if (type == null)
                return null;

            if (context == null)
                return type;

            // Visit recursively and replace generic parameters with generic arguments from context
            var genericInstanceTypeContext = context.DeclaringType as GenericInstanceType;
            var genericInstanceMethodContext = context as GenericInstanceMethod;
            if (genericInstanceMethodContext == null && genericInstanceTypeContext == null)
                return type;

            var visitor = new ResolveGenericsVisitor(context, resolveOnlyReferences);
            var result = visitor.VisitDynamic(type);

            return result;
        }
예제 #9
0
        /// <summary>
        /// Transform open generic types to closed instantiation using context information.
        /// As an example, if B{T} inherits from A{T}, running it with B{C} as context and A{B.T} as type, ti will return A{C}.
        /// </summary>
        public static TypeReference Process(TypeReference context, TypeReference type)
        {
            if (type == null)
                return null;

            var genericInstanceTypeContext = context as GenericInstanceType;
            if (genericInstanceTypeContext == null)
                return type;

            // Visit recursively and replace generic parameters with generic arguments from context
            var visitor = new ResolveGenericsVisitor(context);
            var result = visitor.VisitDynamic(type);

            // Make sure type is closed now
            if (result.ContainsGenericParameter)
                throw new InvalidOperationException("Unsupported generic resolution.");

            return result;
        }