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