观察以下简单的源代码:
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
接口(interface)怎么办?所以我采取这些行:
//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:
谁能告诉我我的代码有什么问题?
谢谢。
最佳答案
这似乎重复this question ...
其中points to MSDN:
// Build the method body for the explicit interface
// implementation. The name used for the method body
// can be anything. Here, it is the name of the method,
// qualified by the interface name.
//
MethodBuilder mbIM = tb.DefineMethod("I.M",
MethodAttributes.Private | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual |
MethodAttributes.Final,
null,
Type.EmptyTypes);
ILGenerator il = mbIM.GetILGenerator();
il.Emit(OpCodes.Ldstr, "The I.M implementation of C");
il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine",
new Type[] { typeof(string) }));
il.Emit(OpCodes.Ret);
// DefineMethodOverride is used to associate the method
// body with the interface method that is being implemented.
//
tb.DefineMethodOverride(mbIM, typeof(I).GetMethod("M"));
关于c# - 如何使用reflect.emit发出显式接口(interface)实现?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1822047/