コード例 #1
0
        public MosaMethod LoadGenericMethodInstance(IMethodDefOrRef method, IList <TypeSig> genericArguments, GenericArgumentResolver resolver)
        {
            MosaType declType = GetType(resolver.Resolve(method.DeclaringType.ToTypeSig()));

            MDToken token;

            if (method is MethodDef)
            {
                token = ((MethodDef)method).MDToken;
            }
            else
            {
                token = ((MemberRef)method).ResolveMethodThrow().MDToken;
            }

            MosaMethod mosaMethod = null;
            UnitDesc <MethodDef, MethodSig> desc = null;

            foreach (var m in declType.Methods)
            {
                desc = m.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >();
                if (desc.Token.Token == token)
                {
                    mosaMethod = m;
                    break;
                }
            }

            if (mosaMethod == null)
            {
                throw new AssemblyLoadException();
            }

            List <TypeSig> genericArgs = new List <TypeSig>();

            foreach (var genericArg in genericArguments)
            {
                genericArgs.Add(resolver.Resolve(genericArg));
            }
            resolver.PushMethodGenericArguments(genericArgs);

            // Check for existing generic method instance
            var newSig   = resolver.Resolve(method.MethodSig);
            var comparer = new SigComparer();

            foreach (var m in declType.Methods)
            {
                var mDesc = m.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >();
                if (mDesc.Definition == desc.Definition && comparer.Equals(mDesc.Signature, newSig))
                {
                    return(m);
                }
            }

            mosaMethod = metadata.Controller.CreateMethod(mosaMethod);

            using (var _mosaMethod = metadata.Controller.MutateMethod(mosaMethod))
            {
                bool hasOpening = mosaMethod.DeclaringType.HasOpenGenericParams;
                foreach (var genericArg in genericArguments)
                {
                    var newGenericArg = resolver.Resolve(genericArg);
                    hasOpening |= newGenericArg.HasOpenGenericParameter();
                    _mosaMethod.GenericArguments.Add(GetType(newGenericArg));
                }

                _mosaMethod.UnderlyingObject = desc.Clone(newSig);
                _mosaMethod.DeclaringType    = declType;

                _mosaMethod.HasOpenGenericParams = hasOpening;
            }

            resolver.PopMethodGenericArguments();

            using (var decl = metadata.Controller.MutateType(declType))
                decl.Methods.Add(mosaMethod);

            metadata.Resolver.EnqueueForResolve(mosaMethod);

            return(mosaMethod);
        }
コード例 #2
0
        private void ResolveMethod(MosaMethod method)
        {
            GenericArgumentResolver resolver = new GenericArgumentResolver();
            bool hasOpening = method.DeclaringType.HasOpenGenericParams;

            if (method.DeclaringType.GenericArguments.Count > 0)
            {
                foreach (var i in method.DeclaringType.GenericArguments.GetGenericArguments())
                {
                    hasOpening |= i.HasOpenGenericParameter();
                }
                resolver.PushTypeGenericArguments(method.DeclaringType.GenericArguments.GetGenericArguments());
            }

            if (method.GenericArguments.Count > 0)
            {
                foreach (var i in method.GenericArguments.GetGenericArguments())
                {
                    hasOpening |= i.HasOpenGenericParameter();
                }
                resolver.PushMethodGenericArguments(method.GenericArguments.GetGenericArguments());
            }

            using (var mosaMethod = metadata.Controller.MutateMethod(method))
            {
                var desc = method.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >();

                MosaType returnType = metadata.Loader.GetType(resolver.Resolve(desc.Signature.RetType));
                hasOpening |= returnType.HasOpenGenericParams;
                List <MosaParameter> pars = new List <MosaParameter>();

                Debug.Assert(desc.Signature.GetParamCount() + (desc.Signature.HasThis ? 1 : 0) == desc.Definition.Parameters.Count);
                foreach (var param in desc.Definition.Parameters)
                {
                    if (!param.IsNormalMethodParameter)
                    {
                        continue;
                    }
                    var paramType = metadata.Loader.GetType(resolver.Resolve(desc.Signature.Params[param.MethodSigIndex]));
                    var parameter = metadata.Controller.CreateParameter();

                    using (var mosaParameter = metadata.Controller.MutateParameter(parameter))
                    {
                        mosaParameter.Name = param.Name;
                        mosaParameter.ParameterAttributes = (MosaParameterAttributes)param.ParamDef.Attributes;
                        mosaParameter.ParameterType       = paramType;
                        mosaParameter.DeclaringMethod     = method;
                        ResolveCustomAttributes(mosaParameter, param.ParamDef);
                    }

                    pars.Add(parameter);
                    hasOpening |= paramType.HasOpenGenericParams;
                }

                mosaMethod.Signature = new MosaMethodSignature(returnType, pars);

                foreach (var methodImpl in desc.Definition.Overrides)
                {
                    Debug.Assert(methodImpl.MethodBody == desc.Definition);
                    mosaMethod.Overrides.Add(ResolveMethodOperand(methodImpl.MethodDeclaration, null));
                }

                if (desc.Definition.HasBody)
                {
                    ResolveBody(desc.Definition, mosaMethod, desc.Definition.Body, resolver);
                }

                mosaMethod.HasOpenGenericParams = hasOpening;

                ResolveCustomAttributes(mosaMethod, desc.Definition);
            }
        }
コード例 #3
0
        public MosaMethod LoadGenericMethodInstance(IMethodDefOrRef method, IList <TypeSig> genericArguments, GenericArgumentResolver resolver)
        {
            var declType = GetType(resolver.Resolve(method.DeclaringType.ToTypeSig()));

            MDToken token;

            if (method is MethodDef)
            {
                token = ((MethodDef)method).MDToken;
            }
            else
            {
                token = ((MemberRef)method).ResolveMethodThrow().MDToken;
            }

            MosaMethod mosaMethod = null;
            UnitDesc <MethodDef, MethodSig> desc = null;

            foreach (var m in declType.Methods)
            {
                desc = m.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >();
                if (desc.Token.Token == token)
                {
                    mosaMethod = m;
                    break;
                }
            }

            if (mosaMethod == null)
            {
                throw new AssemblyLoadException();
            }

            var genericArgs = new List <TypeSig>();

            foreach (var genericArg in genericArguments)
            {
                genericArgs.Add(resolver.Resolve(genericArg));
            }

            resolver.PushMethodGenericArguments(genericArgs);

            // Check for existing generic method instance
            var newSig = resolver.Resolve(method.MethodSig);

            // Need to make sure we pop otherwise it will cause bugs
            resolver.PopMethodGenericArguments();

            var comparer = new SigComparer();

            foreach (var m in declType.Methods)
            {
                var mDesc = m.GetUnderlyingObject <UnitDesc <MethodDef, MethodSig> >();
                if (mDesc.Definition != desc.Definition || !comparer.Equals(mDesc.Signature, newSig))
                {
                    continue;
                }

                if (newSig.ContainsGenericParameter || newSig.GenParamCount > 0)
                {
                    continue;
                }

                if (m.GenericArguments.Count != genericArgs.Count)
                {
                    continue;
                }

                if (m.GenericArguments.Count > 0)
                {
                    var failedGenericArgumentMatch = false;
                    for (var i = 0; i < m.GenericArguments.Count; i++)
                    {
                        if (comparer.Equals(genericArguments[i], m.GenericArguments[i].GetTypeSig()))
                        {
                            continue;
                        }

                        failedGenericArgumentMatch = true;
                        break;
                    }

                    if (failedGenericArgumentMatch)
                    {
                        continue;
                    }
                }

                return(m);
            }

            mosaMethod = metadata.Controller.CreateMethod(mosaMethod);

            using (var _mosaMethod = metadata.Controller.MutateMethod(mosaMethod))
            {
                bool hasOpening = mosaMethod.DeclaringType.HasOpenGenericParams;
                foreach (var genericArg in genericArgs)
                {
                    hasOpening |= genericArg.HasOpenGenericParameter();
                    var t = GetType(genericArg);
                    if (!_mosaMethod.GenericArguments.Contains(t))
                    {
                        _mosaMethod.GenericArguments.Add(t);
                    }
                }

                _mosaMethod.UnderlyingObject = desc.Clone(newSig);
                _mosaMethod.DeclaringType    = declType;

                _mosaMethod.HasOpenGenericParams = hasOpening;
            }

            using (var decl = metadata.Controller.MutateType(declType))
                decl.Methods.Add(mosaMethod);

            metadata.Resolver.EnqueueForResolve(mosaMethod);

            return(mosaMethod);
        }