【问题标题】:I'm attempting to write a .NET compiler using System.Reflection.Emit how do I do type resolution?我正在尝试使用 System.Reflection.Emit 编写一个 .NET 编译器,我该如何进行类型解析?
【发布时间】:2010-02-09 16:03:03
【问题描述】:

我有一个从引用的 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 库,但如果有更好的方法可以做到这一点,或者不能用它们完成,那么使用其他库是可以接受的。

谢谢

【问题讨论】:

  • 类型推断!= 解析程序集中的类型。类型推断是基于从它们的使用方式获得的证据(如在 F# 中所做的那样)静态推断源代码中未明确提及的内容类型的任务。解析类型只是根据名称查找类型。你指的是哪一个?
  • 解析类型,很抱歉造成混淆。

标签: .net compiler-construction reflection.emit compiler-theory


【解决方案1】:

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

编辑

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

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

【讨论】:

  • @wawa - 查看我的编辑以了解如何按照您的要求进行操作。
  • 如果A和B中定义了其他方法和属性怎么办?在创建完类型的所有成员之前,我可以在 DefineAutoProp 中使用 TypeBuilder 吗?
  • @wawa - 是的。即使在此示例中,TypeBuilder A 上的属性 getter 和 setter 在作为类型传递给 DefineAutoProp 之前也没有创建。该类型仅在调用 CreateType 时才有效冻结。但是,对于特别复杂的相互引用,以特定顺序在 TypeBuilders 上调用 CreateType 可能很重要(例如,如果您要定义嵌套类,则应首先在包含类型上调用 CreateType)。
  • 很好的答案。我唯一的问题是,如果名为“anInstanceOfA”的字段已经存在,您将遇到自动生成的支持字段的问题。也许应该采取更多步骤来确保唯一性。
猜你喜欢
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
  • 2016-02-21
相关资源
最近更新 更多