internal static Method GetMethodInstanceReference(Method methodOfGenericType, TypeNode instantiatedParentType) { //F: Contract.Requires(methodOfGenericType != null); Contract.Requires(instantiatedParentType != null); return (Method)GetMemberInstanceReference(methodOfGenericType, instantiatedParentType); #if false int index = MemberIndexInTypeMembers(methodOfGenericType); // now try to find same index in instance wrapper type Method instMethod = null; var members = instantiatedParentType.Members; if (index < members.Count) { instMethod = members[index] as Method; Debug.Assert(instMethod == null || instMethod.Name.UniqueIdKey == methodOfGenericType.Name.UniqueIdKey); } if (instMethod == null) { // instantiation order did not work out, so we need to fake it. Duplicator dup = new Duplicator(this.assemblyBeingRewritten, instantiatedParentType); dup.RecordOriginalAsTemplate = true; instMethod = dup.VisitMethod(methodOfGenericType); var spec = TypeParameterSpecialization(methodOfGenericType.DeclaringType, instantiatedParentType); instMethod = spec.VisitMethod(instMethod); instMethod.DeclaringType = instantiatedParentType; AddMemberAtIndex(index, instantiatedParentType, instMethod); } return instMethod; #endif }
private static void AddInterfaceImplementationWrapper(Class Class, Method intfMethod, Method baseMethod) { var d = new Duplicator(Class.DeclaringModule, Class); d.SkipBodies = true; var copy = d.VisitMethod(baseMethod); copy.Flags = MethodFlags.Private | MethodFlags.HideBySig | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.Final; copy.ImplementedInterfaceMethods = new MethodList(intfMethod); copy.Name = Identifier.For("InheritedInterfaceImplementationContractWrapper$" + intfMethod.Name.Name); copy.ClearBody(); copy.ThisParameter.Type = Class; var bodyBlock = new Block(new StatementList()); copy.Body = new Block(new StatementList(bodyBlock)); // add call to baseMethod var calledMethod = (baseMethod.TemplateParameters != null && baseMethod.TemplateParameters.Count > 0) ? baseMethod.GetTemplateInstance(Class, copy.TemplateParameters) : baseMethod; var argList = new ExpressionList(); for (int i = 0; i < copy.Parameters.Count; i++) { argList.Add(copy.Parameters[i]); } var callExpression = new MethodCall(new MemberBinding(copy.ThisParameter, calledMethod), argList); if (HelperMethods.IsVoidType(intfMethod.ReturnType)) { bodyBlock.Statements.Add(new ExpressionStatement(callExpression)); } else { bodyBlock.Statements.Add(new Return(callExpression)); } Class.Members.Add(copy); }
public virtual Method/*!*/ GetTemplateInstance(TypeNode referringType, TypeNodeList typeArguments) { if(referringType == null || this.DeclaringType == null) { Debug.Assert(false); return this; } if(this.IsGeneric) referringType = this.DeclaringType; if(referringType != this.DeclaringType && referringType.DeclaringModule == this.DeclaringType.DeclaringModule) return this.GetTemplateInstance(this.DeclaringType, typeArguments); if(referringType.structurallyEquivalentMethod == null) referringType.structurallyEquivalentMethod = new TrivialHashtableUsingWeakReferences(); Module module = referringType.DeclaringModule; if(module == null) return this; int n = typeArguments == null ? 0 : typeArguments.Count; if(n == 0 || typeArguments == null) return this; StringBuilder sb = new StringBuilder(this.Name.ToString()); sb.Append('<'); for(int i = 0; i < n; i++) { TypeNode ta = typeArguments[i]; if(ta == null) continue; sb.Append(ta.FullName); if(i < n - 1) sb.Append(','); } sb.Append('>'); Identifier mangledName = Identifier.For(sb.ToString()); lock(this) { Method m = (Method)referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey]; int counter = 1; while(m != null) { if(m.template == this && Method.TypeListsAreEquivalent(m.TemplateArguments, typeArguments)) return m; mangledName = Identifier.For(mangledName.ToString() + counter++); m = (Method)referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey]; } Duplicator duplicator = new Duplicator(referringType.DeclaringModule, referringType); duplicator.RecordOriginalAsTemplate = true; duplicator.SkipBodies = true; Method result = duplicator.VisitMethod(this); //^ assume result != null; result.Attributes = this.Attributes; //These do not get specialized, but may need to get normalized result.Name = mangledName; result.fullName = null; result.template = this; result.TemplateArguments = typeArguments; TypeNodeList templateParameters = result.TemplateParameters; result.TemplateParameters = null; result.IsNormalized = true; if(!this.IsGeneric) { ParameterList pars = this.Parameters; ParameterList rpars = result.Parameters; if(pars != null && rpars != null && rpars.Count >= pars.Count) for(int i = 0, count = pars.Count; i < count; i++) { Parameter p = pars[i]; Parameter rp = rpars[i]; if(p == null || rp == null) continue; rp.Attributes = p.Attributes; //These do not get specialized, but may need to get normalized } } if(!this.IsGeneric && !(result.IsStatic) && this.DeclaringType != referringType) { result.Flags &= ~(MethodFlags.Virtual | MethodFlags.NewSlot); result.Flags |= MethodFlags.Static; result.CallingConvention &= ~CallingConventionFlags.HasThis; result.CallingConvention |= CallingConventionFlags.ExplicitThis; ParameterList pars = result.Parameters; if(pars == null) result.Parameters = pars = new ParameterList(); Parameter thisPar = new Parameter(StandardIds.This, this.DeclaringType); pars.Add(thisPar); for(int i = pars.Count - 1; i > 0; i--) pars[i] = pars[i - 1]; pars[0] = thisPar; } referringType.structurallyEquivalentMethod[mangledName.UniqueIdKey] = result; Specializer specializer = new Specializer(module, templateParameters, typeArguments); specializer.VisitMethod(result); if(this.IsGeneric) { result.DeclaringType = this.DeclaringType; return result; } if(this.IsAbstract) return result; referringType.Members.Add(result); return result; } }