Je tente d'écrire un compilateur .NET en utilisant System.Reflection.Emit comment puis-je tape la résolution?
-
19-09-2019 - |
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
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 TypeBuilder
s 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 TypeBuilder
s 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();
}