Je tente d'écrire un compilateur .NET en utilisant System.Reflection.Emit comment puis-je tape la résolution?

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

Question

J'ai une stratégie pour résoudre les types de dlls référencés. Je suis coincé à essayer de résoudre les types qui sont définis dans l'assemblée qui est en cours d'élaboration. J'utilise les APIs System.Reflection.Emit sans bibliothèques 3ème partie.

Par exemple:

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

Quelle est la meilleure façon de résoudre la référence B de A?

Qu'en est-il ceci:

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

où les classes contiennent des instances de l'autre.

Y at-il une meilleure façon pratique de le faire? Tous les modèles de conception que je devrais mettre en œuvre? Je préfère utiliser uniquement les librarys de System.Reflection.Emit mais s'il y a une meilleure façon de faire ceci ou cela ne peut être fait avec eux, puis à l'aide d'autres bibliothèques (s) est acceptable.

Merci

Était-ce utile?

La solution

Pourriez-vous préciser la question que vous utilisez en (peut-être un code montrant un petit exemple de code qui ne fonctionne pas pour vous)? Parce que TypeBuilder dérive de Type, si vous essayez de définir des types mutuellement récursifs, vous pouvez passer les deux TypeBuilders où vous souhaitez faire référence aux types.

EDIT

Il n'y a pas besoin de « résoudre » les types. Vous avez accès aux TypeBuilders pour chacun et peut les utiliser comme si elles y étaient types définis. Voici un exemple qui génère le code demandé dans votre mise à jour:

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top