Der folgende Code soll Klassen und Schnittstellen ausgeben, die dem folgenden C# entsprechen
Code: Select all
public interface MyInterface1
{
void IfaceMethod(int arg);
}
public interface MyInterface2
{
void IfaceMethod(int arg);
}
public interface MyInterface3
{
void IfaceMethod(T arg);
}
public class MyClass : MyInterface1, MyInterface2, MyInterface3
{
void MyInterface1.IfaceMethod(int arg)
{
Console.WriteLine(...);
}
void MyInterface2.IfaceMethod(int arg)
{
Console.WriteLine(...);
}
void MyInterface3.IfaceMethod(int arg)
{
Console.WriteLine(...);
}
}
Code: Select all
using System.Reflection;
using System.Reflection.Emit;
class Test
{
static void Main()
{
string example_name = "Interface example";
AssemblyName asm_name = new AssemblyName(example_name);
AssemblyBuilder asm_builder = AssemblyBuilder.DefineDynamicAssembly(asm_name, AssemblyBuilderAccess.Run);
ModuleBuilder module_builder = asm_builder.DefineDynamicModule(example_name);
TypeBuilder class_builder = module_builder.DefineType("MyClass", TypeAttributes.Public | TypeAttributes.Class);
TypeBuilder interface1_builder = module_builder.DefineType("MyInterface1", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
TypeBuilder interface2_builder = module_builder.DefineType("MyInterface2", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
TypeBuilder interface3_builder = module_builder.DefineType("MyInterface3", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
Type[] interface2_generics = interface2_builder.DefineGenericParameters(["T"]);
Type[] interface3_generics = interface3_builder.DefineGenericParameters(["T"]);
MethodAttributes method_attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Abstract;
interface1_builder.DefineMethod("IfaceMethod", method_attributes, null, [typeof(int)]);
interface2_builder.DefineMethod("IfaceMethod", method_attributes, null, [typeof(int)]);
interface3_builder.DefineMethod("IfaceMethod", method_attributes, null, interface3_generics);
Type interface1_type = interface1_builder.CreateType();
Type interface2_type = interface2_builder.CreateType();
Type interface3_type = interface3_builder.CreateType();
/* Now let MyClass implement IfaceMethod from MyInterface1, MyInterface2 and MyInterface3 */
List interfaces = new List();
// Interface1 always works
interfaces.Add(interface1_type);
// Interface2 errors with: Unhandled exception. System.TypeLoadException: Type 'MyClass' from assembly
// 'Interface example, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' tried to override
// method 'fn_0' but does not implement or inherit that method.
interfaces.Add(interface2_type.MakeGenericType([typeof(double)]));
// Interface3 errors with: Unhandled exception. System.TypeLoadException: Signature of the body and
// declaration in a method implementation do not match. Type: 'MyClass'. Assembly:
// 'Interface example, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
interfaces.Add(interface3_type.MakeGenericType([typeof(int)]));
List methods = new List();
for(int i = 0; i < interfaces.Count; i++){
Type interface_type = interfaces[i];
class_builder.AddInterfaceImplementation(interface_type);
string method_name = "fn_"+i;
MethodBuilder class_method = class_builder.DefineMethod(method_name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, null, [typeof(int)]);
ILGenerator il = class_method.GetILGenerator();
il.EmitWriteLine("Hello from " + method_name + " implementing IfaceMethod from " + interface_type.Name);
il.Emit(OpCodes.Ret);
MethodInfo interface_method = interface_type.GetMethod("IfaceMethod");
class_builder.DefineMethodOverride(class_method, interface_method);
methods.Add(interface_method);
}
Type class_type = class_builder.CreateType();
object obj = Activator.CreateInstance(class_type);
Object[] args = [123];
foreach(MethodInfo method in methods){
method.Invoke(obj, args);
}
}
}
Die Fehlermeldung, wenn ich versuche, MyInterface2 zu implementieren, lautet
Code: Select all
Unhandled exception. System.TypeLoadException: Type 'MyClass' from
assembly 'Interface example, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null' tried to override method 'fn_0' but does not
implement or inherit that method.
at System.Reflection.Emit.RuntimeTypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.RuntimeTypeBuilder.CreateTypeInfoImpl()
at Test.Main() in C:\tmp\interface-issue\Program.cs:line 62
Code: Select all
Unhandled exception. System.TypeLoadException: Signature of the body
and declaration in a method implementation do not match.
Type: 'MyClass'. Assembly: 'Interface example, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
at System.Reflection.Emit.RuntimeTypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.RuntimeTypeBuilder.CreateTypeInfoImpl()
at Test.Main() in C:\tmp\interface-issue\Program.cs:line 62
Jeder Hinweis darauf, was mir hier fehlt, wäre dankbar. Ich habe dies sowohl mit .NET 8.0 als auch mit .NET 9.0 versucht und es gibt keinen Unterschied.
Bearbeiten: korrigierte Version basierend auf der unten akzeptierten Lösung.
Code: Select all
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using System.Linq;
class Test
{
static void Main()
{
string example_name = "Interface example";
AssemblyName asm_name = new AssemblyName(example_name);
AssemblyBuilder asm_builder = AssemblyBuilder.DefineDynamicAssembly(asm_name, AssemblyBuilderAccess.Run);
ModuleBuilder module_builder = asm_builder.DefineDynamicModule(example_name);
TypeBuilder class_builder = module_builder.DefineType("MyClass", TypeAttributes.Public | TypeAttributes.Class);
TypeBuilder interface1_builder = module_builder.DefineType("MyInterface1", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
TypeBuilder interface2_builder = module_builder.DefineType("MyInterface2", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
TypeBuilder interface3_builder = module_builder.DefineType("MyInterface3", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);
Type[] interface2_generics = interface2_builder.DefineGenericParameters(["T"]);
Type[] interface3_generics = interface3_builder.DefineGenericParameters(["T"]);
MethodAttributes method_attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Abstract;
List interface_method_builders = new List();
interface_method_builders.Add(interface1_builder.DefineMethod("IfaceMethod", method_attributes, null, [typeof(int)]));
interface_method_builders.Add(interface2_builder.DefineMethod("IfaceMethod", method_attributes, null, [typeof(int)]));
interface_method_builders.Add(interface3_builder.DefineMethod("IfaceMethod", method_attributes, null, interface3_generics));
interface1_builder.CreateType();
interface2_builder.CreateType();
interface3_builder.CreateType();
List interfaces = new List();
interfaces.Add(interface1_builder);
interfaces.Add(interface2_builder.MakeGenericType([typeof(double)]));
interfaces.Add(interface3_builder.MakeGenericType([typeof(int)]));
for(int i = 0; i < interfaces.Count; i++){
Type interface_type = interfaces[i];
MethodInfo interface_method = interface_method_builders[i];
try
{
interface_method = TypeBuilder.GetMethod(interface_type, interface_method); /* in case it was from a generic interface*/
}
catch(Exception)
{
}
class_builder.AddInterfaceImplementation(interface_type);
string method_name = "fn_"+i;
MethodBuilder class_method = class_builder.DefineMethod(method_name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, null, [typeof(int)]);
ILGenerator il = class_method.GetILGenerator();
il.EmitWriteLine("Hello from " + method_name + " implementing IfaceMethod from " + interface_type.Name);
il.Emit(OpCodes.Ret);
class_builder.DefineMethodOverride(class_method, interface_method);
}
Type class_type = class_builder.CreateType();
object obj = Activator.CreateInstance(class_type);
List methods = class_type.GetInterfaces().Select(i => i.GetMethod("IfaceMethod")).ToList();
Object[] args = [123];
foreach(MethodInfo method in methods){
method.Invoke(obj, args);
}
}
}
Mobile version