Я пытаюсь написать компилятор .NET, используя System.Отражение.Испускать как мне выполнить разрешение типов?

StackOverflow https://stackoverflow.com/questions/2230440

Вопрос

У меня есть стратегия для разрешения типов из библиотек dll, на которые ссылаются ссылки.Я застрял в попытке разрешить типы, которые определены в компилируемой сборке.Я использую систему.Отражение.Генерирую 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.Отражение.Выдавать библиотеки, но если есть лучший способ сделать это или это невозможно сделать с ними, то использование других библиотек приемлемо.

Спасибо

Это было полезно?

Решение

Не могли бы вы подробнее рассказать о проблеме, с которой вы столкнулись (возможно, показав code небольшой пример кода, который у вас не работает)?Потому что 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();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top