创建类型“MyClass:OtherClass< MyClass> {}“在运行时? [英] Create type "MyClass : OtherClass<MyClass> { }" at runtime?

查看:152
本文介绍了创建类型“MyClass:OtherClass< MyClass> {}“在运行时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能在C#中在运行时创建一个继承自基类的模板参数是当前正在构造的类的泛型类的类型?这将编译得很好:

  //我有这个类:
public class OtherClass< T>
其中T:OtherClass< T>
{}

//我想在运行时创建它:
public class MyClass:OtherClass< MyClass>
{}

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

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

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

TypeBuilder tb = modb.DefineType(
test,
TypeAttributes.Public | TypeAttributes.Class,
typeof(MyClass)); //如何指定继承?

//填充属性,字段,方法等等,发出...

tb.CreateType();

这可能吗?

编辑 - 根据到目前为止的回复,我已经试过了:

  public class OtherClass< T> 
其中T:OtherClass< T>
{}

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

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

键入my = tb.CreateType();
tb.SetParent(typeof(OtherClass<>)。MakeGenericType(my));

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


$ / code>

但是得到这个例外:

$ b 'MyProject.Factory + OtherClass`1上的
$ b

  GenericArguments [0],'MyClass'1 [T]'
违反了' T。


解决方案

编辑:这是我最后的工作答案: p>

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

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

TypeBuilder tb = modb.DefineType(
test,
TypeAttributes.Public | TypeAttributes.Class);
// Typebuilder是Type
的子类tb.SetParent(typeof(OtherClass<>)。MakeGenericType(tb));
var t2 = tb.CreateType();
var i = Activator.CreateInstance(t2);

诀窍是使用参数化的泛型类型调用SetParent,参数是类型的类型构建器构建自己。






使用 TypeBuilder.SetParent(父类型)方法。



使用它时要小心,异常抛出延迟到 CreateType 调用:




在.NET Framework版本1.0和1.1中,如果parent是一个接口,则不会引发异常类型,但在调用CreateType方法时抛出TypeLoadException。



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


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

  var genericType = typeof(OtherClass<>)。MakeGenericType(typeof我的课)); 


Is it possible in C# to create a type at runtime that inherits from a generic class where the template parameter for the base class is the current class being constructed? This will compile fine:

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

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

but I'm not sure how to create the MyClass using System.Reflection.Emit.ModuleBuilder.TypeBuilder:

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();

Is this possible?

Edit - Based on replies so far, I've tried this:

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;
    }
}

but get this exception:

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

解决方案

Edit : Here is my final working answer :

        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);

The trick is to call SetParent with a parametrised generic type, the parameter is the typebuilder of the type being constructed itself.


Use the TypeBuilder.SetParent(Type parent) method.

Be careful when using it, exception throwing is deferred to CreateType call :

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.

To build your generic type OtherClass<T>, use the MakeGenericType method :

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

这篇关于创建类型“MyClass:OtherClass&lt; MyClass&gt; {}“在运行时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆