我正在尝试使用 System.Reflection.Emit 编写 .NET 编译器,如何进行类型解析?

发布于 2024-08-20 14:54:07 字数 499 浏览 3 评论 0原文

我有一个从引用的 dll 解析类型的策略。我一直在尝试解析正在编译的程序集中定义的类型。我使用的是 System.Reflection.Emit api,没有第三方库。

例如:

class A {}
class B
{
    public A AnInstanceOfA {get; private set;}
}

解决 B 对 A 的引用的最佳方法是什么?

怎么样:

class A
{
    B AnInstanceOfB {get; set;}
}
class B
{
    A AnInstanceOfA {get; set;}
}

类包含彼此的实例。

有没有最佳实践方法来做到这一点?我应该实施什么设计模式?我更愿意仅使用 System.Reflection.Emit 库,但如果有更好的方法来执行此操作或者无法使用它们来完成此操作,那么使用其他库是可以接受的。

谢谢

I've got a strategy for resolving types from referenced dlls. I'm stuck on trying to resolve types that are defined in the assembly that is being compiled. I'm using the System.Reflection.Emit apis with no 3rd party libraries.

For instance:

class A {}
class B
{
    public A AnInstanceOfA {get; private set;}
}

What's the best way to resolve B's reference of A?

What about this:

class A
{
    B AnInstanceOfB {get; set;}
}
class B
{
    A AnInstanceOfA {get; set;}
}

where the classes contain instances of each other.

Is there a best practice way to do this? Any design patterns I should implement? I would prefer to use only the System.Reflection.Emit librarys but if there is a better way to do this or this can't be done with them, then using other library(s) is acceptable.

Thanks

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

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

发布评论

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

评论(1

苦行僧 2024-08-27 14:54:07

您能否详细说明您遇到的问题(也许向代码显示一个不适合您的代码的小示例)?由于 TypeBuilder 派生自 Type,因此如果您尝试定义相互递归类型,您可以将两个 TypeBuilder 传递到您想要的任何位置参考类型。

编辑

无需“解析”类型。您可以访问每个类型的 TypeBuilder,并且可以像使用完全定义的类型一样使用它们。以下是生成您在更新中请求的代码的示例:

private void DefineAutoProp(string name, Type t, TypeBuilder tb)
{
    var fldName = name.Substring(0, 1).ToLower() + name.Substring(1);
    var fld = tb.DefineField(fldName, t, FieldAttributes.Private);
    var prop = tb.DefineProperty(name, PropertyAttributes.None, t, null);
    var getter = tb.DefineMethod("get_" + name, MethodAttributes.Public, t, null);
    var ilg = getter.GetILGenerator();
    ilg.Emit(OpCodes.Ldarg_0);
    ilg.Emit(OpCodes.Ldfld, fld);
    ilg.Emit(OpCodes.Ret);
    var setter = tb.DefineMethod("set_" + name, MethodAttributes.Public, typeof(void), new[] { t });
    ilg = setter.GetILGenerator();
    ilg.Emit(OpCodes.Ldarg_0);
    ilg.Emit(OpCodes.Ldarg_1);
    ilg.Emit(OpCodes.Stfld, fld);
    ilg.Emit(OpCodes.Ret);
    prop.SetGetMethod(getter);
    prop.SetSetMethod(setter);
}

public void DefineTypes()
{
    var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("test"), AssemblyBuilderAccess.Run);
    var mb = ab.DefineDynamicModule("test");
    var A = mb.DefineType("A", TypeAttributes.Public | TypeAttributes.Class);
    var B = mb.DefineType("B", TypeAttributes.Public | TypeAttributes.Class);
    DefineAutoProp("AnInstanceOfA", A, B);
    DefineAutoProp("AnInstanceOfB", B, A);
    A.CreateType();
    B.CreateType();
}

Could you elaborate on the issue that you're running into (perhaps showing code a small example of code that isn't working for you)? Because TypeBuilder derives from Type, if you're trying to define mutually recursive types you can pass the two TypeBuilders wherever you'd like to refer to the types.

EDIT

There's no need to "resolve" the types. You have access to the TypeBuilders for each and can use them just as if they were fully defined types. Here's an example that generates the code you requested in your update:

private void DefineAutoProp(string name, Type t, TypeBuilder tb)
{
    var fldName = name.Substring(0, 1).ToLower() + name.Substring(1);
    var fld = tb.DefineField(fldName, t, FieldAttributes.Private);
    var prop = tb.DefineProperty(name, PropertyAttributes.None, t, null);
    var getter = tb.DefineMethod("get_" + name, MethodAttributes.Public, t, null);
    var ilg = getter.GetILGenerator();
    ilg.Emit(OpCodes.Ldarg_0);
    ilg.Emit(OpCodes.Ldfld, fld);
    ilg.Emit(OpCodes.Ret);
    var setter = tb.DefineMethod("set_" + name, MethodAttributes.Public, typeof(void), new[] { t });
    ilg = setter.GetILGenerator();
    ilg.Emit(OpCodes.Ldarg_0);
    ilg.Emit(OpCodes.Ldarg_1);
    ilg.Emit(OpCodes.Stfld, fld);
    ilg.Emit(OpCodes.Ret);
    prop.SetGetMethod(getter);
    prop.SetSetMethod(setter);
}

public void DefineTypes()
{
    var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("test"), AssemblyBuilderAccess.Run);
    var mb = ab.DefineDynamicModule("test");
    var A = mb.DefineType("A", TypeAttributes.Public | TypeAttributes.Class);
    var B = mb.DefineType("B", TypeAttributes.Public | TypeAttributes.Class);
    DefineAutoProp("AnInstanceOfA", A, B);
    DefineAutoProp("AnInstanceOfB", B, A);
    A.CreateType();
    B.CreateType();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文