如何使用 Reflection.emit 发出显式接口实现?
请观察以下简单的源代码:
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
namespace A
{
public static class Program
{
private const MethodAttributes ExplicitImplementation =
MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final |
MethodAttributes.HideBySig | MethodAttributes.NewSlot;
private const MethodAttributes ImplicitImplementation =
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig;
private static Type EmitMyIntfType(ModuleBuilder moduleBuilder)
{
var typeBuilder = moduleBuilder.DefineType("IMyInterface",
TypeAttributes.NotPublic | TypeAttributes.Interface | TypeAttributes.Abstract);
typeBuilder.DefineMethod("MyMethod", MethodAttributes.Assembly | MethodAttributes.Abstract |
MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
typeof(void), new[] { typeof(int) });
return typeBuilder.CreateType();
}
public static void Main()
{
var assemblyName = new AssemblyName("DynamicTypesAssembly");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll", true);
var myIntfType = EmitMyIntfType(moduleBuilder);
var typeBuilder = moduleBuilder.DefineType("MyType",
TypeAttributes.Public | TypeAttributes.BeforeFieldInit | TypeAttributes.Serializable |
TypeAttributes.Sealed, typeof(object), new[] { myIntfType });
//var myMethodImpl = typeBuilder.DefineMethod("IMyInterface.MyMethod", ExplicitImplementation,
// null, new[] { typeof(int) });
var myMethodImpl = typeBuilder.DefineMethod("MyMethod", ImplicitImplementation,
null, new[] { typeof(int) });
var ilGenerator = myMethodImpl.GetILGenerator();
ilGenerator.Emit(OpCodes.Ret);
var type = typeBuilder.CreateType();
assemblyBuilder.Save("A.dll");
}
}
}
下面是通过使用 Reflector 反编译 A.dll 程序集获得的等效 C# 代码:
internal interface IMyInterface
{
void MyMethod(int);
}
[Serializable]
public sealed class MyType : IMyInterface
{
public override void MyMethod(int)
{
}
}
现在,如果我希望 MyType
类型实现 IMyInterface
该怎么办?显式接口? 因此,我采用以下几行:
//var myMethodImpl = typeBuilder.DefineMethod("IMyInterface.MyMethod", ExplicitImplementation,
// null, new[] { typeof(int) });
var myMethodImpl = typeBuilder.DefineMethod("MyMethod", ImplicitImplementation,
null, new[] { typeof(int) });
并切换注释以生成此代码:
var myMethodImpl = typeBuilder.DefineMethod("IMyInterface.MyMethod", ExplicitImplementation,
null, new[] { typeof(int) });
// var myMethodImpl = typeBuilder.DefineMethod("MyMethod", ImplicitImplementation,
// null, new[] { typeof(int) });
但现在,应用程序无法创建动态类型。这一行:
var type = typeBuilder.CreateType();
抛出以下异常:
System.TypeLoadException was unhandled
Message="Method 'MyMethod' in type 'MyType' from assembly 'DynamicTypesAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation."
Source="mscorlib"
TypeName="MyType"
StackTrace:
at System.Reflection.Emit.TypeBuilder._TermCreateClass(Int32 handle, Module module)
at System.Reflection.Emit.TypeBuilder.TermCreateClass(Int32 handle, Module module)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at A.Program.Main() in C:\Home\work\A\Program.cs:line 45
InnerException:
任何人都可以告诉我我的代码有什么问题吗?
谢谢。
Observe the following simple source code:
using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
namespace A
{
public static class Program
{
private const MethodAttributes ExplicitImplementation =
MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final |
MethodAttributes.HideBySig | MethodAttributes.NewSlot;
private const MethodAttributes ImplicitImplementation =
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig;
private static Type EmitMyIntfType(ModuleBuilder moduleBuilder)
{
var typeBuilder = moduleBuilder.DefineType("IMyInterface",
TypeAttributes.NotPublic | TypeAttributes.Interface | TypeAttributes.Abstract);
typeBuilder.DefineMethod("MyMethod", MethodAttributes.Assembly | MethodAttributes.Abstract |
MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
typeof(void), new[] { typeof(int) });
return typeBuilder.CreateType();
}
public static void Main()
{
var assemblyName = new AssemblyName("DynamicTypesAssembly");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll", true);
var myIntfType = EmitMyIntfType(moduleBuilder);
var typeBuilder = moduleBuilder.DefineType("MyType",
TypeAttributes.Public | TypeAttributes.BeforeFieldInit | TypeAttributes.Serializable |
TypeAttributes.Sealed, typeof(object), new[] { myIntfType });
//var myMethodImpl = typeBuilder.DefineMethod("IMyInterface.MyMethod", ExplicitImplementation,
// null, new[] { typeof(int) });
var myMethodImpl = typeBuilder.DefineMethod("MyMethod", ImplicitImplementation,
null, new[] { typeof(int) });
var ilGenerator = myMethodImpl.GetILGenerator();
ilGenerator.Emit(OpCodes.Ret);
var type = typeBuilder.CreateType();
assemblyBuilder.Save("A.dll");
}
}
}
Below is the equivalent C# code obtained by decompiling the A.dll assembly using the Reflector:
internal interface IMyInterface
{
void MyMethod(int);
}
[Serializable]
public sealed class MyType : IMyInterface
{
public override void MyMethod(int)
{
}
}
Now what if I wish the MyType
type implement the IMyInterface
interface explicitly?
So I take these lines:
//var myMethodImpl = typeBuilder.DefineMethod("IMyInterface.MyMethod", ExplicitImplementation,
// null, new[] { typeof(int) });
var myMethodImpl = typeBuilder.DefineMethod("MyMethod", ImplicitImplementation,
null, new[] { typeof(int) });
and switch the comments to yield this code:
var myMethodImpl = typeBuilder.DefineMethod("IMyInterface.MyMethod", ExplicitImplementation,
null, new[] { typeof(int) });
// var myMethodImpl = typeBuilder.DefineMethod("MyMethod", ImplicitImplementation,
// null, new[] { typeof(int) });
But now, the application fails to create the dynamic type. This line:
var type = typeBuilder.CreateType();
throws the following exception:
System.TypeLoadException was unhandled
Message="Method 'MyMethod' in type 'MyType' from assembly 'DynamicTypesAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation."
Source="mscorlib"
TypeName="MyType"
StackTrace:
at System.Reflection.Emit.TypeBuilder._TermCreateClass(Int32 handle, Module module)
at System.Reflection.Emit.TypeBuilder.TermCreateClass(Int32 handle, Module module)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at A.Program.Main() in C:\Home\work\A\Program.cs:line 45
InnerException:
Can anyone show me what is wrong with my code?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这似乎与这个问题重复......
哪个指向 MSDN:
That seems duplicate to this question...
Which points to MSDN: