首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >当接口位于便携式类库中时,PEVerify在显式接口属性上失败

当接口位于便携式类库中时,PEVerify在显式接口属性上失败
EN

Stack Overflow用户
提问于 2015-02-03 22:42:48
回答 1查看 235关注 0票数 0

我正在发出一个类,它使用get方法显式地实现一个简单的接口属性。只要在可移植类库中没有定义接口,就不会有任何问题。但是,当将接口移动到PCL并仅使用特定类型(如IEnumerable<int> )时,PEVerify将失败。

查看ILDASM -> MetaInfo -> Show,您将看到mscorlibSystem.Runtime程序集引用都是导入的。这发生在对DefineMethodOverride的调用过程中(观察AssemblyBuilder.GetReferencedAssemblies()以查看)。您还可以看到,IEnumerable`1 `1是作为来自两个程序集的TypeRef引入的,这似乎就是问题所在。

当不将接口分离到PCL,或者将类型更改为其他类型时,它可以工作,并且不包含System.Runtime引用。要尝试string,请将IEnumerable<int>替换为接口中的string以及DefineProperty/DefineMethod调用。

使用修改后的示例来自MSDN作为重现此问题的简化方法,将下面的代码放在控制台项目中,一切都很好。将interface I移动到一个可移植类库项目中,您将看到我的确切意思。

如何消除PEVerify错误?

错误:MethodImpl‘match (token=0x0a000001)和Body (token=0x00610072)方法签名不匹配。令牌:0x19000001

代码语言:javascript
代码运行次数:0
运行
复制
public interface I
{
    IEnumerable<int> E { get; }
}

class Test
{
    static void Main()
    {
        string name = "DefineMethodOverrideExample";
        AssemblyName asmName = new AssemblyName(name);
        AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder mb = ab.DefineDynamicModule(name, name + ".dll");
        TypeBuilder tb = mb.DefineType("C", TypeAttributes.Public);
        tb.AddInterfaceImplementation(typeof(I));

        PropertyBuilder prop = tb.DefineProperty("I.E", PropertyAttributes.None, typeof(IEnumerable<int>), Type.EmptyTypes);

        MethodBuilder mbIM = tb.DefineMethod(
            "I.get_E",
            MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.SpecialName,
            typeof(IEnumerable<int>),
            Type.EmptyTypes);
        prop.SetGetMethod(mbIM);

        ILGenerator il = mbIM.GetILGenerator();
        il.Emit(OpCodes.Ldnull);
        il.Emit(OpCodes.Ret);

        tb.DefineMethodOverride(mbIM, typeof(I).GetProperty("E").GetGetMethod());

        Type tc = tb.CreateType();

        ab.Save(name + ".dll");
    }
}

(.Net 4.5.1)

(PEVerify和ILDASM版本4.0.30319.33440来自C:\Program (x86)\Microsoft \Windows\v8.1A\bin\NETFX4.5.1工具\x64)

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-04 20:26:28

在与已发出和编译的示例进行更多比较之后,以及深入研究.NET库之后,我能够发现关键的区别在于对ModuleBuilder.DefineMethodOverrideNoLock -> GetMethodTokenInternalNoLock (在接口上)的调用,其中有一个测试提供的MethodInfo是否为RuntimeMethodInfo。最终,对GetMemberRefOfMethodInfo的调用会导致System.Runtime的包含,从而为某些类型产生冲突的结果,例如IEnumerable

要以不需要反映到私有成员的方式解决这个问题,您可以创建继承MethodInfo的代理或包装器,该代理或包装器覆盖所有方法以返回来自原始RuntimeMethodInfo的结果。这将导致ILDASM显示出现在编译(未发出)程序集中的TypeRef和TypeSpec元素,试图显式实现PCL接口方法。我能够使用此技术成功地验证发出的程序集。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28310167

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档