2012-09-14 3 views
7

自分の言語用にコンパイラを作っているので、私はReflection.Emitフレームワークを使ってMSILコードを生成しようとしています。ローカル変数を宣言するときにはintを使用するとうまく動作します。しかし、私がまだコンパイルしていない型のローカル変数を宣言したいときは、DeclareLocal()が引数としてTypeを引数に取るので、問題が発生します。それは私のコンパイルされていないクラスである、Aを言って、まだあなたがここに必要な主要な洞察力がそのTypeBuilderで、どのように私が今までに以下のプログラムILGenerator.DeclareLocal()はまだコンパイルされていないクラスの型を取る

class A { 
    void M() { B b = new B(); } 
} 
class B 
    void M() { A a = new A(); } 
} 
+0

何が役立ちますか? –

+1

@phoog:彼は誰かが自分の仕事をするのを待っているかもしれません。 –

+0

実際にはC#はここにはありません。それは円の依存関係の例に過ぎません –

答えて

7

をコンパイルすることができるようになります

assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemName, AssemblyBuilderAccess.RunAndSave); 
module = assemblyBuilder.DefineDynamicModule(Filename); 
module.DefineType(name, TypeAttributes.Public | TypeAttributes.Class) 

を使用して定義する必要がありますTypeに由来します。したがって、タイプをまだファイナライズしていなくても(CreateType()を呼び出して)、それを使って別のタイプのローカル変数を宣言することができます。

私が遭遇したもう1つの障壁は、未完了のTypeBuilderGetConstructor()が機能しないことです(例外がスローされます)。しかし、デフォルトのコンストラクタを明示的に作成した場合は、ConstructorBuilderから呼び出すことができます。

static void Main() 
{ 
    var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
     new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave); 
    var module = assemblyBuilder.DefineDynamicModule("foo.dll"); 
    var aType = module.DefineType(
     "A", TypeAttributes.Public | TypeAttributes.Class); 
    var bType = module.DefineType(
     "B", TypeAttributes.Public | TypeAttributes.Class); 
    var aCtor = aType.DefineDefaultConstructor(MethodAttributes.Public); 
    var bCtor = bType.DefineDefaultConstructor(MethodAttributes.Public); 
    CreateMethodM(aType, bType, bCtor); 
    CreateMethodM(bType, aType, aCtor); 
    aType.CreateType(); 
    bType.CreateType(); 
    assemblyBuilder.Save("foo.dll"); 
} 

static void CreateMethodM(
    TypeBuilder thisType, Type otherType, ConstructorInfo otherCtor) 
{ 
    var method = thisType.DefineMethod(
     "M", MethodAttributes.Private, typeof(void), Type.EmptyTypes); 
    var il = method.GetILGenerator(); 
    var local = il.DeclareLocal(otherType); 
    il.Emit(OpCodes.Newobj, otherCtor); 
    il.Emit(OpCodes.Stloc, local); 
    il.Emit(OpCodes.Ret); 
} 
+1

Argh!私のソリューションはあなたにとても近いです! –

+2

DeclaringTypeは、何か違うものです。例えば、ネストされた型の場合など、この型が宣言された型を表します。 – svick

関連する問題