Приведенный ниже код должен генерировать классы и интерфейсы, эквивалентные следующему C#
Код: Выделить всё
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(...);
}
}
Код: Выделить всё
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);
}
}
}
При попытке реализовать MyInterface2 появляется сообщение об ошибке
Код: Выделить всё
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
Код: Выделить всё
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
Любые намеки на то, чего мне здесь не хватает, будут оценены по достоинству. Я пробовал это, используя как .NET 8.0, так и .NET 9.0, разницы нет.
Подробнее здесь: https://stackoverflow.com/questions/798 ... ich-implem
Мобильная версия