如何使用 Mono.Cecil 为接口方法实现别名?
我使用 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() { }
}
我得到的是一个 < code>PEVerify.exe 错误,表明我的类不再实现接口方法。似乎在更改的程序集中重写引用和接口中的方法之间存在标记不匹配:
[MD]: Error: Class implements interface but not method (class:0x02000004; interface:0x02000002; method:0x06000001). [token:0x09000001]
我知道如果我直接使用 MethodDefinition
它将起作用:
targetMethod.Overrides.Add(sourceMethod);
但我确实需要使用 < code>MethodReference 因为我可能在所涉及的类型中具有通用参数和实参,而简单的 MethodDefinition
是不行的。
更新:按照Jb Evain,我已经迁移到版本 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);
I'm using Mono.Cecil
(version 0.6.9.0) to alias a method that implements an interface method. To do that, I have to add an Override
to the target method that points back to the interface method (much like what's possible with VB.NET), like this:
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() { }
}
What I'm getting is a PEVerify.exe
error that indicates that my class doesn't implement the interface method anymore. It seems that there's a token mismatch in the changed assembly between the override reference and the method in the interface:
[MD]: Error: Class implements interface but not method (class:0x02000004; interface:0x02000002; method:0x06000001). [token:0x09000001]
I know that if I use the MethodDefinition
directly it will work:
targetMethod.Overrides.Add(sourceMethod);
But I really need to use a MethodReference
because I might have generic parameters and arguments in the types involved, and a simple MethodDefinition
won't do.
Update: As recommended by Jb Evain, I've migrated to version 0.9.3.0. But, the same error still happens. Here's the migrated code:
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是使用 0.6 的烦恼之一。您必须将新创建的 MethodReference 放入模块的 .MemberReferences 集合中。
我强烈建议你切换到0.9。
That's one of the annoyance of using the 0.6. You have to put the newly created MethodReference in the .MemberReferences collection of your module.
I strongly suggest you switch to 0.9.