List <IMethod> GetMethods(TypeDef declaringType, BabelMethodreference babelMethodRef) { var methods = new List <IMethod>(); var gis = babelMethodRef.DeclaringType as GenericInstSig; var gim = babelMethodRef.GenericArguments; foreach (var method in declaringType.Methods) { if (CompareMethod(GenericArgsSubstitutor.Create(method, gis, gim), babelMethodRef)) { if (!babelMethodRef.IsGenericMethod) { methods.Add(memberRefConverter.Convert(method)); } else { var gim2 = new GenericInstMethodSig(babelMethodRef.GenericArguments); var ms = module.UpdateRowId(new MethodSpecUser(memberRefConverter.Convert(method), gim2)); methods.Add(ms); } } } return(methods); }
public void InitializeFrom(MethodInstances other, GenericInstSig git) { foreach (var list in other.methodInstances.Values) { foreach (var methodInst in list) { var newMethod = GenericArgsSubstitutor.Create(methodInst.methodRef, git); Add(new MethodInst(methodInst.origMethodDef, newMethod)); } } }
public MethodBase Resolve(IMethod methodRef) { InitMethods(); if (!methods.TryGetValue(methodRef.Name.String, out var list)) { return(null); } methodRef = GenericArgsSubstitutor.Create(methodRef, methodRef.DeclaringType.TryGetGenericInstSig()); foreach (var method in list) { if (ResolverUtils.CompareMethods(method, methodRef)) { return(method); } } return(null); }
public FieldInfo Resolve(IField fieldRef) { InitFields(); if (!fields.TryGetValue(fieldRef.Name.String, out var list)) { return(null); } fieldRef = GenericArgsSubstitutor.Create(fieldRef, fieldRef.DeclaringType.TryGetGenericInstSig()); foreach (var field in list) { if (ResolverUtils.CompareFields(field, fieldRef)) { return(field); } } return(null); }
void InitializeInterfaceMethods(MethodNameGroups groups) { InitializeAllInterfaces(); if (TypeDef.IsInterface) { return; } //--- Partition II 12.2 Implementing virtual methods on interfaces: //--- The VES shall use the following algorithm to determine the appropriate //--- implementation of an interface's virtual abstract methods: //--- //--- * If the base class implements the interface, start with the same virtual methods //--- that it provides; otherwise, create an interface that has empty slots for all //--- virtual functions. // Done. See initializeAllInterfaces(). var methodsDict = new Dictionary <IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.DontCompareDeclaringTypes); //--- * If this class explicitly specifies that it implements the interface (i.e., the //--- interfaces that appear in this class‘ InterfaceImpl table, §22.23) //--- * If the class defines any public virtual newslot methods whose name and //--- signature match a virtual method on the interface, then use these new virtual //--- methods to implement the corresponding interface method. if (interfaces.Count > 0) { methodsDict.Clear(); foreach (var method in methods.GetValues()) { if (!method.IsPublic() || !method.IsVirtual() || !method.IsNewSlot()) { continue; } methodsDict[method.MethodDef] = method; } foreach (var ifaceInfo in interfaces) { foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods()) { if (methodsList.Count < 1) { continue; } var methodInst = methodsList[0]; var ifaceMethod = methodInst.origMethodDef; if (!ifaceMethod.IsVirtual()) { continue; } var ifaceMethodRef = GenericArgsSubstitutor.Create(methodInst.methodRef, ifaceInfo.typeRef.TryGetGenericInstSig()); MMethodDef classMethod; if (!methodsDict.TryGetValue(ifaceMethodRef, out classMethod)) { continue; } interfaceMethodInfos.AddMethod(ifaceInfo, ifaceMethod, classMethod); } } } //--- * If there are any virtual methods in the interface that still have empty slots, //--- see if there are any public virtual methods, but not public virtual newslot //--- methods, available on this class (directly or inherited) having the same name //--- and signature, then use these to implement the corresponding methods on the //--- interface. methodsDict.Clear(); foreach (var methodInstList in virtualMethodInstances.GetMethods()) { // This class' method is at the end for (int i = methodInstList.Count - 1; i >= 0; i--) { var classMethod = methodInstList[i]; // These methods are guaranteed to be virtual. // We should allow newslot methods, despite what the official doc says. if (!classMethod.origMethodDef.IsPublic()) { continue; } methodsDict[classMethod.methodRef] = classMethod.origMethodDef; break; } } foreach (var ifaceInfo in allImplementedInterfaces.Keys) { foreach (var methodsList in ifaceInfo.typeDef.virtualMethodInstances.GetMethods()) { if (methodsList.Count < 1) { continue; } var ifaceMethod = methodsList[0].origMethodDef; if (!ifaceMethod.IsVirtual()) { continue; } var ifaceMethodRef = GenericArgsSubstitutor.Create(ifaceMethod.MethodDef, ifaceInfo.typeRef.TryGetGenericInstSig()); MMethodDef classMethod; if (!methodsDict.TryGetValue(ifaceMethodRef, out classMethod)) { continue; } interfaceMethodInfos.AddMethodIfEmpty(ifaceInfo, ifaceMethod, classMethod); } } //--- * Apply all MethodImpls that are specified for this class, thereby placing //--- explicitly specified virtual methods into the interface in preference to those //--- inherited or chosen by name matching. methodsDict.Clear(); var ifaceMethodsDict = new Dictionary <IMethodDefOrRef, MMethodDef>(MethodEqualityComparer.CompareDeclaringTypes); foreach (var ifaceInfo in allImplementedInterfaces.Keys) { var git = ifaceInfo.typeRef.TryGetGenericInstSig(); foreach (var ifaceMethod in ifaceInfo.typeDef.methods.GetValues()) { IMethodDefOrRef ifaceMethodRef = ifaceMethod.MethodDef; if (git != null) { ifaceMethodRef = SimpleClone(ifaceMethod.MethodDef, ifaceInfo.typeRef); } ifaceMethodsDict[ifaceMethodRef] = ifaceMethod; } } foreach (var classMethod in methods.GetValues()) { if (!classMethod.IsVirtual()) { continue; } foreach (var overrideMethod in classMethod.MethodDef.Overrides) { MMethodDef ifaceMethod; if (!ifaceMethodsDict.TryGetValue(overrideMethod.MethodDeclaration, out ifaceMethod)) { // We couldn't find the interface method (eg. interface not resolved) or // it overrides a base class method, and not an interface method. continue; } interfaceMethodInfos.AddMethod(overrideMethod.MethodDeclaration.DeclaringType, ifaceMethod, classMethod); } } //--- * If the current class is not abstract and there are any interface methods that //--- still have empty slots, then the program is invalid. // Check it anyway. C# requires a method, even if it's abstract. I don't think anyone // writes pure CIL assemblies. foreach (var info in interfaceMethodInfos.AllInfos) { foreach (var pair in info.IfaceMethodToClassMethod) { if (pair.Value != null) { continue; } if (!ResolvedAllInterfaces() || !ResolvedBaseClasses()) { continue; } // Ignore if COM class if (!TypeDef.IsImport && !HasAttribute("System.Runtime.InteropServices.ComImportAttribute") && !HasAttribute("System.Runtime.InteropServices.TypeLibTypeAttribute")) { Logger.w("Could not find interface method {0} ({1:X8}). Type: {2} ({3:X8})", Utils.RemoveNewlines(pair.Key.methodDef.MethodDef), pair.Key.methodDef.MethodDef.MDToken.ToInt32(), Utils.RemoveNewlines(TypeDef), TypeDef.MDToken.ToInt32()); } } } foreach (var info in interfaceMethodInfos.AllInfos) { foreach (var pair in info.IfaceMethodToClassMethod) { if (pair.Value == null) { continue; } if (pair.Key.methodDef.MethodDef.Name != pair.Value.MethodDef.Name) { continue; } groups.Same(pair.Key.methodDef, pair.Value); } } }
public TypeInfo(TypeInfo other, GenericInstSig git) { this.typeRef = GenericArgsSubstitutor.Create(other.typeRef, git); this.typeDef = other.typeDef; }