问题描述
想象一下下面的完全合法的类型层次:
Imagine the following perfectly legal type hierarchy:
class A<T> where T : A<T>
{
}
class B : A<B>
{
public B():base(){}
}
我的问题是给A&LT的静态编译定义;?>是它可以动态地发出B型
My question is given a statically compiled definition of A<> is it possible to emit the type B dynamically?
现在的问题是如何在 ModuleBuilder.DefineType
指定父类型。
The problem is how to specify the parent type in ModuleBuilder.DefineType
.
或者,也许有另一种方式来生产这种类型的,除了
Or maybe there is another way to produce such a type, other than
- 使用上述方法
- 使用codeDOM(这很像创建一个临时文件,将其传递给CSC.EXE: - ))
编辑:类型 B
应该有明确的公共默认构造函数调用默认的构造函数继承自 A&LT; B&GT;
The type B
should have explicit public default constructor invoking the default constructor inherited from A<B>
.
推荐答案
您可以使用 ModuleBuilder.DefineType
过载不指定一个父类,然后使用 TypeBuilder.SetParent
方法父设置递归式(使用参数类似于的typeof(A&LT;&GT;。)MakeGenericType(TB )
,其中 TB
是 TypeBuilder
,但我没有一个C#编译器我前面)。
You can use an overload of ModuleBuilder.DefineType
which doesn't specify a parent type, and then use the TypeBuilder.SetParent
method to set the parent to the recursive type (using an argument something like typeof(A<>).MakeGenericType(tb)
where tb
is your TypeBuilder
, but I don't have a C# compiler in front of me).
修改 - 这里有一个工作的例子,假设你有一个 ModuleBuilder MB
。对于一个空的默认构造函数,你并不需要使用 DefineConstructor
办法可言;另外,您可以使用 DefineDefaultConstructor
。我已经包含其中基础构造函数显式调用,但举例来说,如果你有一些额外的逻辑,你想在里面添加。
EDIT - here's a working example, assuming you've got a ModuleBuilder mb
. For an empty default constructor, you don't need to use the DefineConstructor
method at all; alternatively you could use DefineDefaultConstructor
. I've included an example where the base constructor is explicitly called, though, in case you have some extra logic you want to add in there.
TypeBuilder tb = mb.DefineType("B");
Type AB = typeof(A<>).MakeGenericType(tb);
tb.SetParent(AB);
ConstructorInfo ctor = TypeBuilder.GetConstructor(AB, typeof(A<>).GetConstructor(new Type[] { }));
ILGenerator ilg = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { }).GetILGenerator();
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Call, ctor);
ilg.Emit(OpCodes.Ret);
Type t = tb.CreateType();
这篇关于是否有可能发出一个类型从一个泛型类型,同时指定自己的泛型类型参数派生?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!