是否可以发出从泛型类型派生的类型,同时将其自身指定为泛型类型参数?

发布于 2024-08-04 06:06:15 字数 468 浏览 2 评论 0原文

想象一下以下完全合法的类型层次结构:

class A<T> where T : A<T>
{
}

class B : A<B>
{
  public B():base(){}
}

我的问题给出了 A<> 的静态编译定义。是否可以动态发出 B 类型?

问题是如何在ModuleBuilder.DefineType中指定父类型。

或者也许还有另一种方法来生成这样的类型,除了

  • 使用上述使用 CodeDom 的方法
  • (这很像创建一个临时文件并将其传递给 csc.exe :-))

编辑: 类型 B 应该具有显式公共默认构造函数,调用从 A 继承的默认构造函数。

Imagine the following perfectly legal type hierarchy:

class A<T> where T : A<T>
{
}

class B : A<B>
{
  public B():base(){}
}

My question is given a statically compiled definition of A<> is it possible to emit the type B dynamically?

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

  • using the aforementioned method
  • using CodeDom (which is much like creating a temporary file and passing it to csc.exe :-))

EDIT:
The type B should have explicit public default constructor invoking the default constructor inherited from A<B>.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

栀子花开つ 2024-08-11 06:06:15

您可以使用不指定父类型的 ModuleBuilder.DefineType 重载,然后使用 TypeBuilder.SetParent 方法将父类型设置为递归类型(使用类似 typeof(A<>).MakeGenericType(tb) 的参数,其中 tb 是您的 TypeBuilder,但我没有我面前的 C# 编译器)。

编辑 - 这是一个工作示例,假设您有一个ModuleBuilder mb。对于空的默认构造函数,您根本不需要使用 DefineConstructor 方法;或者您可以使用DefineDefaultConstructor。不过,我提供了一个显式调用基本构造函数的示例,以防您想要在其中添加一些额外的逻辑。

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

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

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文