我试图编写使用System.Reflection.Emit我怎么输入分辨率的.NET编译器?编译器、分辨率、我怎么、Reflection

2023-09-04 02:55:50 作者:落言

我已经有了一个战略,从引用的DLL文件解析的类型。我卡在试图解决在正在编译的程序集定义的类型。我使用System.Reflection.Emit的API,没有第三方库。

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.

例如:

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

什么是解决A和B的参考的最佳方法是什么?

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

怎么样的:

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

所在班互相牵制的实例。

where the classes contain instances of each other.

有没有一种最佳实践的方式来做到这一点?任何设计模式我应该实现?我想preFER只使用System.Reflection.Emit图书馆的,但如果有更好的方法来做到这一点还是这不能跟他们做的,然后用其他图书馆(s)是可以接受的。

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.

感谢

推荐答案

你能否详细说明你正在运行到(可能呈现出code,它不为你工作,codeA小例子问题)?因为 TypeBuilder 派生类型,如果你想定义相互递归类型,你可以通过两个 TypeBuilder 取值无论你想引用类型。

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.

修改

有没有需要解决的类型。您有机会获得 TypeBuilder S表示每使用它们,就好像他们是完全定义的类型。下面是产生code您在您的更新请求的例子:

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