Quan sát mã nguồn đơn giản sau đây:Làm thế nào để phát ra thực hiện giao diện rõ ràng bằng cách sử dụng 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");
}
}
}
Dưới đây là tương đương với C# code thu được bằng cách dịch ngược assembly A.dll sử dụng Reflector:
internal interface IMyInterface
{
void MyMethod(int);
}
[Serializable]
public sealed class MyType : IMyInterface
{
public override void MyMethod(int)
{
}
}
Bây giờ những gì nếu tôi muốn loại MyType
thực hiện giao diện IMyInterface
một cách rõ ràng? Vì vậy, tôi lấy những dòng này:
//var myMethodImpl = typeBuilder.DefineMethod("IMyInterface.MyMethod", ExplicitImplementation,
// null, new[] { typeof(int) });
var myMethodImpl = typeBuilder.DefineMethod("MyMethod", ImplicitImplementation,
null, new[] { typeof(int) });
và chuyển đổi các ý kiến để mang mã này:
var myMethodImpl = typeBuilder.DefineMethod("IMyInterface.MyMethod", ExplicitImplementation,
null, new[] { typeof(int) });
// var myMethodImpl = typeBuilder.DefineMethod("MyMethod", ImplicitImplementation,
// null, new[] { typeof(int) });
Nhưng bây giờ, các ứng dụng không tạo ra các loại năng động. Dòng này:
var type = typeBuilder.CreateType();
ném ngoại lệ sau đây:
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:
bất cứ ai có thể chỉ cho tôi những gì là sai với mã của tôi?
Cảm ơn.
Trên thực tế đó là, mặc dù tôi đã nhận thấy câu hỏi đó và thậm chí đã đến thăm các bài viết MSDN, nhưng sau khi đọc đoạn đầu tiên trong phần chú thích từ bỏ nó. Chỉ cần không nghĩ về việc thực hiện giao diện rõ ràng như đặt tên khác cho phương thức giao diện. Bây giờ tôi thấy sai lầm của tôi. Cảm ơn. – mark
Đó là lý do tại sao việc xem xét mã hoạt động!) –