private static void SetupOverwriteReferences(INameService service, ICollection <ModuleDefMD> modules, VTableSlot slot, TypeDef thisType) { var module = thisType.Module; var methodDef = slot.MethodDef; var baseSlot = slot.Overrides; var baseMethodDef = baseSlot.MethodDef; var overrideRef = new OverrideDirectiveReference(slot, baseSlot); service.AddReference(methodDef, overrideRef); service.AddReference(slot.Overrides.MethodDef, overrideRef); var importer = new Importer(module, ImporterOptions.TryToUseTypeDefs); IMethodDefOrRef target; if (baseSlot.MethodDefDeclType is GenericInstSig declType) { MemberRef targetRef = new MemberRefUser(module, baseMethodDef.Name, baseMethodDef.MethodSig, declType.ToTypeDefOrRef()); targetRef = importer.Import(targetRef); service.AddReference(baseMethodDef, new MemberRefReference(targetRef, baseMethodDef)); SetupSignatureReferences(service, modules, module, targetRef.DeclaringType.ToTypeSig() as GenericInstSig); target = targetRef; } else { target = baseMethodDef; if (target.Module != module) { target = (IMethodDefOrRef)importer.Import(baseMethodDef); if (target is MemberRef memberRef) { service.AddReference(baseMethodDef, new MemberRefReference(memberRef, baseMethodDef)); } } } if (target is MemberRef methodRef) { AddImportReference(service, modules, module, baseMethodDef, methodRef); } if (TypeEqualityComparer.Instance.Equals(methodDef.DeclaringType, thisType)) { if (methodDef.Overrides.Any(impl => IsMatchingOverride(impl, target))) { return; } methodDef.Overrides.Add(new MethodOverride(methodDef, target)); } else if (target is IMemberDef targetDef) { CreateOverrideReference(service, methodDef, targetDef); } }
private static void SetupOverwriteReferences(ConfuserContext context, INameService service, VTableSlot slot, ModuleDef module) { var methodDef = slot.MethodDef; var baseSlot = slot.Overrides; var baseMethodDef = baseSlot.MethodDef; var overrideRef = new OverrideDirectiveReference(slot, baseSlot); service.AddReference(methodDef, overrideRef); service.AddReference(slot.Overrides.MethodDef, overrideRef); var importer = new Importer(module, ImporterOptions.TryToUseTypeDefs); IMethod target; if (baseSlot.MethodDefDeclType is GenericInstSig declType) { var signature = SetupSignatureReferences(context, service, module, declType); MemberRef targetRef = new MemberRefUser(module, baseMethodDef.Name, baseMethodDef.MethodSig, signature.ToTypeDefOrRef()); targetRef = importer.Import(targetRef); service.AddReference(baseMethodDef, new MemberRefReference(targetRef, baseMethodDef)); target = targetRef; } else { target = baseMethodDef; if (target.Module != module) { target = importer.Import(baseMethodDef); if (target is MemberRef memberRef) { service.AddReference(baseMethodDef, new MemberRefReference(memberRef, baseMethodDef)); } } } target.MethodSig = importer.Import(methodDef.MethodSig); if (target is MemberRef methodRef) { AddImportReference(context, service, module, baseMethodDef, methodRef); } if (methodDef.Overrides.Any(impl => new SigComparer().Equals(impl.MethodDeclaration.MethodSig, target.MethodSig) && new SigComparer().Equals(impl.MethodDeclaration.DeclaringType.ResolveTypeDef(), target.DeclaringType.ResolveTypeDef()))) { return; } methodDef.Overrides.Add(new MethodOverride(methodDef, (IMethodDefOrRef)target)); }
private static void SetupOverwriteReferences(INameService service, ICollection <ModuleDefMD> modules, VTableSlot slot, TypeDef thisType) { var module = thisType.Module; var methodDef = slot.MethodDef; var baseSlot = slot.Overrides; var baseMethodDef = baseSlot.MethodDef; var overrideRef = new OverrideDirectiveReference(slot, baseSlot); service.AddReference(methodDef, overrideRef); service.AddReference(slot.Overrides.MethodDef, overrideRef); var importer = new Importer(module, ImporterOptions.TryToUseTypeDefs); IMethodDefOrRef target; if (baseSlot.MethodDefDeclType is GenericInstSig declType) { MemberRef targetRef = new MemberRefUser(module, baseMethodDef.Name, baseMethodDef.MethodSig, declType.ToTypeDefOrRef()); targetRef = importer.Import(targetRef); service.AddReference(baseMethodDef, new MemberRefReference(targetRef, baseMethodDef)); SetupSignatureReferences(service, modules, module, targetRef.DeclaringType.ToTypeSig() as GenericInstSig); target = targetRef; } else { target = baseMethodDef; if (target.Module != module) { target = (IMethodDefOrRef)importer.Import(baseMethodDef); if (target is MemberRef memberRef) { service.AddReference(baseMethodDef, new MemberRefReference(memberRef, baseMethodDef)); } } } if (target is MemberRef methodRef) { AddImportReference(service, modules, module, baseMethodDef, methodRef); } if (TypeEqualityComparer.Instance.Equals(methodDef.DeclaringType, thisType)) { if (methodDef.Overrides.Any(impl => IsMatchingOverride(impl, target))) { return; } methodDef.Overrides.Add(new MethodOverride(methodDef, target)); } else if (target is IMemberDef targetDef) { // Reaching this place means that a slot of the base type is overwritten by a specific interface. // In case the this type is implementing the interface responsible for this, we need to declare // this as an override reference. If the base type is implementing the interface (as well), this // declaration is redundant. var overrideRefRequired = true; if (targetDef.DeclaringType.IsInterface) { var baseTypeDef = thisType.BaseType?.ResolveTypeDef(); if (!(baseTypeDef is null)) { var baseTypeVTable = service.GetVTables()[baseTypeDef]; if (baseTypeVTable.InterfaceSlots.TryGetValue(targetDef.DeclaringType.ToTypeSig(), out var ifcSlots)) { overrideRefRequired = !ifcSlots.Contains(slot); } } } if (overrideRefRequired) { CreateOverrideReference(service, methodDef, targetDef); } } }