Eu estou tentando escrever um compilador .NET usando System.Reflection.Emit como eu faço resolução do tipo?

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

Pergunta

Eu tenho uma estratégia para resolver os tipos de DLLs referenciadas. Eu estou preso em tentar resolver os tipos que são definidos na assembléia que está sendo compilado. Estou usando as APIs System.Reflection.Emit sem bibliotecas 3o partido.

Por exemplo:

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

Qual é a melhor maneira de referência determinação de B de A?

O que sobre isso:

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

onde as classes contêm instâncias de outro.

Existe uma melhor maneira prática de fazer isso? Quaisquer padrões de design que eu deveria implementar? Eu preferiria usar apenas os librarys System.Reflection.Emit mas se há uma maneira melhor de fazer isso ou isso não pode ser feito com eles, em seguida, usando outra biblioteca (s) é aceitável.

Graças

Foi útil?

Solução

Você poderia elaborar sobre o problema que você está correndo em (talvez mostrando código de um pequeno exemplo de código que não está funcionando para você)? Porque deriva TypeBuilder de Type, se você está tentando definir tipos mutuamente recursivas você pode passar as duas TypeBuilders onde quer que você gostaria de se referir aos tipos.

Editar

Não há necessidade de "resolver" os tipos. Você tem acesso aos TypeBuilders para cada um e pode usá-los como se eles foram totalmente tipos definidos. Aqui está um exemplo que gera o código solicitado na sua actualização:

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();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top