当接口位于可移植 Class 库中时,PEVerify 在显式接口 属性 上失败
PEVerify fails on explicit interface property when the interface is in a Portable Class Library
我正在发出一个 class,它使用 get 方法显式实现了一个简单的接口 属性。只要接口未在可移植 class 库中定义,就没有问题。但是,当将接口移动到 PCL 并仅使用特定类型(例如 IEnumerable<int>
时,PEVerify 将失败。
查看 ILDASM -> MetaInfo -> Show,您会看到 mscorlib
和 System.Runtime
程序集引用都已导入。这发生在调用 DefineMethodOverride
期间(观看 AssemblyBuilder.GetReferencedAssemblies()
以查看)。您还可以看到 IEnumerable`1 作为 TypeRef 从两个程序集中引入,这似乎是问题所在。
当不将接口分离为 PCL 时,或者当将类型更改为其他内容时,它可以工作并且不包括 System.Runtime
引用。要尝试 string
,请在界面中将 IEnumerable<int>
替换为 string
以及 DefineProperty
/DefineMethod
调用。
使用修改后的示例 from MSDN 作为重现此问题的简化方法,将下面的代码放入控制台项目中,一切正常。将 interface I
移至可移植的 class 库项目,您将明白我的意思。
如何消除 PEVerify 错误?
Error: MethodImpl's Decl (token=0x0a000001) and Body
(token=0x00610072) method signatures do not match. [token:0x19000001]
[hr:0x801312F4]
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 Files (x86)\Microsoft SDKs\Windows\v8。1A\bin\NETFX 4.5.1 Tools\x64)
谢谢!
在对发出的和编译的示例进行更多比较并深入研究 .NET libraries 之后,我发现关键区别在于对 ModuleBuilder.DefineMethodOverrideNoLock
-> [= 的调用11=](在界面上),其中测试提供的MethodInfo
是否为RuntimeMethodInfo
。最终调用 GetMemberRefOfMethodInfo
会导致包含 System.Runtime
,从而为某些类型产生冲突的结果,例如 IEnumerable
.
为了以不需要反映到私有成员的方式解决这个问题,您可以创建一个继承 MethodInfo
的代理或包装器,它会覆盖原始 return 结果的所有方法 RuntimeMethodInfo
。这将导致 ILDASM 显示出现在试图显式实现 PCL 接口方法的已编译(非发射)程序集中的 TypeRef 和 TypeSpec 元素。我能够使用这种技术成功验证发出的程序集。
我正在发出一个 class,它使用 get 方法显式实现了一个简单的接口 属性。只要接口未在可移植 class 库中定义,就没有问题。但是,当将接口移动到 PCL 并仅使用特定类型(例如 IEnumerable<int>
时,PEVerify 将失败。
查看 ILDASM -> MetaInfo -> Show,您会看到 mscorlib
和 System.Runtime
程序集引用都已导入。这发生在调用 DefineMethodOverride
期间(观看 AssemblyBuilder.GetReferencedAssemblies()
以查看)。您还可以看到 IEnumerable`1 作为 TypeRef 从两个程序集中引入,这似乎是问题所在。
当不将接口分离为 PCL 时,或者当将类型更改为其他内容时,它可以工作并且不包括 System.Runtime
引用。要尝试 string
,请在界面中将 IEnumerable<int>
替换为 string
以及 DefineProperty
/DefineMethod
调用。
使用修改后的示例 from MSDN 作为重现此问题的简化方法,将下面的代码放入控制台项目中,一切正常。将 interface I
移至可移植的 class 库项目,您将明白我的意思。
如何消除 PEVerify 错误?
Error: MethodImpl's Decl (token=0x0a000001) and Body (token=0x00610072) method signatures do not match. [token:0x19000001] [hr:0x801312F4]
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 Files (x86)\Microsoft SDKs\Windows\v8。1A\bin\NETFX 4.5.1 Tools\x64)
谢谢!
在对发出的和编译的示例进行更多比较并深入研究 .NET libraries 之后,我发现关键区别在于对 ModuleBuilder.DefineMethodOverrideNoLock
-> [= 的调用11=](在界面上),其中测试提供的MethodInfo
是否为RuntimeMethodInfo
。最终调用 GetMemberRefOfMethodInfo
会导致包含 System.Runtime
,从而为某些类型产生冲突的结果,例如 IEnumerable
.
为了以不需要反映到私有成员的方式解决这个问题,您可以创建一个继承 MethodInfo
的代理或包装器,它会覆盖原始 return 结果的所有方法 RuntimeMethodInfo
。这将导致 ILDASM 显示出现在试图显式实现 PCL 接口方法的已编译(非发射)程序集中的 TypeRef 和 TypeSpec 元素。我能够使用这种技术成功验证发出的程序集。