c# - 在运行时创建类型 "MyClass : OtherClass<MyClass> { }"?

标签 c# generics reflection runtime

在 C# 中是否可以在运行时创建一个类型,该类型继承自泛型类,其中基类的模板参数是正在构造的当前类?这将编译正常:

// I have this class:
public class OtherClass<T>
    where T : OtherClass<T>
{ }

// I want to create this at runtime:
public class MyClass : OtherClass<MyClass>
{ }

但我不确定如何使用 System.Reflection.Emit.ModuleBuilder.TypeBuilder 创建 MyClass:

AssemblyName asn = new AssemblyName("test.dll");
AssemblyBuilder asb = AppDomain.CurrentDomain.DefineDynamicAssembly(
    asn, AssemblyBuilderAccess.RunAndSave, @"D:\test_assemblies");

ModuleBuilder = modb = asb.DefineDynamicModule("test", "test.dll");

TypeBuilder tb = modb.DefineType(
    "test",
    TypeAttributes.Public | TypeAttributes.Class,
    typeof(MyClass)); // How to specify inheritance?

// populate properties, fields, methods, etc., emit...

tb.CreateType();

这可能吗?

编辑 - 根据目前的回复,我试过这个:

public class OtherClass<T>
    where T : OtherClass<T>
{ }

public static void CreateSimple()
{
    AssemblyName asn = new AssemblyName("test");
    AssemblyBuilder asb = AppDomain.CurrentDomain.DefineDynamicAssembly(
        asn, AssemblyBuilderAccess.RunAndSave, @"D:\test_asms");
    ModuleBuilder modb = asb.DefineDynamicModule("test", "test.dll");

    try
    {
        TypeBuilder tb = modb.DefineType(
            "MyClass",
            TypeAttributes.Public | TypeAttributes.Class);

        Type my = tb.CreateType();
        tb.SetParent(typeof(OtherClass<>).MakeGenericType(my));

        my = tb.CreateType();
    }
    catch (Exception e)
    {
        throw;
    }
}

但是得到这个异常:

GenericArguments[0], 'MyClass', on 'MyProject.Factory+OtherClass`1[T]'
violates the constraint of type 'T'.

最佳答案

编辑:这是我最终的工作答案:

        AssemblyName asn = new AssemblyName("test.dll");
        AssemblyBuilder asb = AppDomain.CurrentDomain.DefineDynamicAssembly(
            asn, AssemblyBuilderAccess.RunAndSave, @"D:\test_assemblies");

        ModuleBuilder modb = asb.DefineDynamicModule("test", "test.dll");

        TypeBuilder tb = modb.DefineType(
            "test",
            TypeAttributes.Public | TypeAttributes.Class);
        // Typebuilder is a sub class of Type
        tb.SetParent(typeof(OtherClass<>).MakeGenericType(tb));
        var t2 = tb.CreateType();
        var i = Activator.CreateInstance(t2);

诀窍是使用参数化泛型调用 SetParent,参数是正在构造的类型本身的类型构建器。


使用 TypeBuilder.SetParent(Type parent)方法。

使用时要小心,异常抛出延迟到CreateType打电话:

If parent is null, Object is used as the base type.

In the .NET Framework versions 1.0 and 1.1, no exception is thrown if parent is an interface type, but a TypeLoadException is thrown when the CreateType method is called.

The SetParent method does not check for most invalid parent types. For example, it does not reject a parent type that has no default constructor when the current type has a default constructor, it does not reject sealed types, and it does not reject the Delegate type. In all these cases, exceptions are thrown by the CreateType method.

构建通用类型 OtherClass<T> , 使用 MakeGenericType方法:

var genericType = typeof(OtherClass<>).MakeGenericType(typeof(MyClass));

关于c# - 在运行时创建类型 "MyClass : OtherClass<MyClass> { }"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13276447/

相关文章:

c# - 使用 C# 类型作为泛型

Java 表达式解析获取对象

scala - 在 Scala 2.10 中获取 java.lang.Class[T] 的 Scala 类型

c# - 使用 JOIN、GROUP BY、SUM 将 SQL 转换为 LINQ,将值相乘两个列表

c# - 投影条件评估不正确

c# - 我可以在 C# 中从 const char 初始化 const 字符串吗?

java - 如何检查java模板方法中的类类型(instanceof)?

c# - 如何在c#中的backgroundworker中打开另一个窗体

java - 具有类型转换的通用原始类型

java - 从 java.util.List<SomeType> 获取类