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



在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致电:

如果父级为null,则将对象用作基本类型。

在.NET Framework版本1.0和1.1中,如果parter是接口类型,则不例外,但是当createType方法称为typeloadexception。

SetParent方法未检查大多数无效的父型类型。例如,当当前类型具有默认构造函数时,它不会拒绝没有默认构造函数的父类型,也不会拒绝密封的类型,也不会拒绝委托类型。在所有这些情况下,创伤方法都会抛出例外。

要构建您的通用类型OtherClass<T>,请使用makeGenerictype方法:

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

您可以在以后设置基本类型。

typebuilder.setparent(type)

是。这是可能的。请参阅Reflection.Emit名称空间和TypeBuilder的方法。

相关内容

最新更新