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

3
我有一个解决从引用的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库,但如果有更好的方法或无法使用它们,则可以使用其他库。

谢谢


3
类型推断并不等同于解析程序集中的类型。类型推断是指根据从使用方式获得的证据,在源代码中未明确提到的内容的情况下,静态地推断类型的任务(例如 F# 中所做的)。而解析类型只是根据它们的名称找到类型。你指的是哪一个? - Mehrdad Afshari
解析类型,对混淆感到抱歉。 - Wesley Wiser
1个回答

3
您遇到了什么问题(可以展示一小段不可用的代码示例),能否详细说明一下?由于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();
}

@wawa - 看看我的编辑,里面有一个你所要求的示例。 - kvb
如果A和B中定义了其他方法和属性,那该怎么办?我能在创建类型的所有成员之前就使用DefineAutoProp中的TypeBuilder吗? - Wesley Wiser
@wawa - 是的。即使在此示例中,在将其作为类型传递给 DefineAutoProp 之前,TypeBuilder A 上的属性 getter 和 setter 也尚未创建。仅当调用 CreateType 时,该类型才是实际上被固定的。但是,对于特别复杂的相互引用,可能需要按特定顺序对 TypeBuilder 调用 CreateType(例如,如果您正在定义嵌套类,则应首先对包含类型调用 CreateType)。 - kvb
很棒的答案。我唯一的问题是,如果已经存在一个名为“anInstanceOfA”的字段,那么您将遇到自动生成的后备字段的问题。也许应该采取更多步骤来确保唯一性。 - captncraig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接