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.
That seems duplicate to this question...
Which points to MSDN:
However, to provide a separate implementation of I.M(), you must define a method body and then use the
DefineMethodOverride
method to associate that method body with aMethodInfo
representing I.M(). The name of the method body does not matter.
// 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"));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With