我正在使用Mono.Cecil
(版本0.6.9.0)来为实现接口方法的方法添加别名。要做到这一点,我必须在目标方法中添加一个Override
,指向接口方法(非常类似于VB.NET),如下所示:
using System;
using System.Reflection;
using Mono.Cecil;
class Program {
static void Main(string[] args) {
var asm = AssemblyFactory.GetAssembly(Assembly.GetExecutingAssembly().Location);
var source = asm.MainModule.Types["A"];
var sourceMethod = source.Methods[0];
var sourceRef = new MethodReference(
sourceMethod.Name,
sourceMethod.DeclaringType,
sourceMethod.ReturnType.ReturnType,
sourceMethod.HasThis,
sourceMethod.ExplicitThis,
sourceMethod.CallingConvention);
var target = asm.MainModule.Types["C"];
var targetMethod = target.Methods[0];
targetMethod.Name = "AliasedMethod";
targetMethod.Overrides.Add(sourceRef);
AssemblyAssert.Verify(asm); // this will just run PEVerify on the changed assembly
}
}
interface A {
void Method();
}
class C : A {
public void Method() { }
}
我得到的是PEVerify.exe
错误,表示我的类不再实现接口方法。似乎在覆盖引用和界面中的方法之间更改的程序集中存在令牌不匹配:
[MD]: Error: Class implements interface but not method (class:0x02000004; interface:0x02000002; method:0x06000001). [token:0x09000001]
我知道如果我直接使用MethodDefinition
,它就会起作用:
targetMethod.Overrides.Add(sourceMethod);
但我真的需要使用MethodReference
,因为我可能在所涉及的类型中有通用参数和参数,而简单的MethodDefinition
则不会。
更新:根据Jb Evain的建议,我migrated版本为0.9.3.0。但是,仍然会发生同样的错误。这是迁移的代码:
var module = ModuleDefinition.ReadModule(Assembly.GetExecutingAssembly().Location);
var source = module.GetType("A");
var sourceMethod = source.Methods[0];
var sourceRef = new MethodReference(
sourceMethod.Name,
sourceMethod.ReturnType) {
DeclaringType = sourceMethod.DeclaringType,
HasThis = sourceMethod.HasThis,
ExplicitThis = sourceMethod.ExplicitThis,
CallingConvention = sourceMethod.CallingConvention
};
var target = module.GetType("C");
var targetMethod = target.Methods[0];
targetMethod.Name = "AliasedMethod";
targetMethod.Overrides.Add(sourceRef);
答案 0 :(得分:3)
这是使用0.6的烦恼之一。您必须将新创建的MethodReference放入模块的.MemberReferences集合中。
我强烈建议您切换到0.9。