2012-11-18 10 views
5

Roslynをベースにしたスクリプトエンジンをアプリケーションに組み込み、いくつかの問題に直面しました。私のエンジンへの参照をロードするとき、私は次の操作を行い実行時にRoslynスクリプトを実行しているときにアセンブリが見つかりません

var engine = new Roslyn.Scripting.CSharp.ScriptEngine(); 
engine.AddReference("MyAssemblyLocation"); 

質問:他のアセンブリを参照している

  1. アセンブリMyAssemblyLocation場合、どのように私はengine.AddReference("MyAssemblyLocation");
  2. を実行せずにそれらをロードするロスリンを教えてくださいスクリプトが実行されているはずのホストアプリケーションはすでにスクリプトで使用したいアセンブリをいくつかロードしていますが、Roslynが既にロードされているDLLの中に自分自身をフックして新しいインスタンスをロードしない方法がありますか?
  3. 最後に、再帰的に

MyAssemblyLocationありがとうのすべての依存関係をロードするためにロスリンを指示する方法があります。

答えて

6

1)短い答え:あなたがタイプをスクリプトで使用する予定のすべてのアセンブリにAddReferenceを追加する必要があります。

詳細: C#コンパイラは、依存ファイルの場所を推測しません。アセンブリファイルは、すべての依存関係への完全なパスを指定していません。名前だけが含まれているため、一般的にコンパイラがアセンブリファイルを見つけるのに十分ではありません。

詳細: 依存関係は2種類あります。コンパイル時の依存関係(a)とランタイム依存関係(b)と呼びます。

(a)アセンブリA.dllに「パブリッククラスA:B {}」、アセンブリB.dllに「パブリッククラスB {}」があり、スクリプトがAを使用しているとします。インスタンス: "新しいA()"コンパイラは、AがBから派生し、コンパイラが使用する各タイプの継承階層を解析する必要があるため、この場合はA.dllとB.dllの両方への参照を追加する必要があります。だからB.dllはあなたのスクリプトのコンパイル時の依存関係です - あなたのスクリプトを適切に解析するためには、コンパイラがそれを必要とします。

(b)別の例を考えてみましょう: "A.dllにpublicクラスA {publicオブジェクトM(){return new B();}}"と同じB.dllがあります。今度は "new A()。M()"をコンパイルするとき、Bの参照はメソッドMの本体でのみ発生し、コンパイラはインポートされたメソッドの本体を解析しないので、コンパイラはBについて知る必要はありません。この場合、スクリプトをコンパイルするために、A.dllへの参照を追加するだけで十分です。スクリプトが実行されると、メソッドMが呼び出されます。その時点でCLRはアセンブリBをロードします。これは少し複雑になるため、詳細はスキップしますが、一般的なシナリオではアセンブリを見つけることができます。参照を明示的に追加する必要はありません。

2)アセンブリオブジェクトを受け取るAddReferenceのオーバーロードを使用することをお勧めします。次のようなものがあります。 engine.AddReference(typeof(SomeTypeInAssemblyFoo).Assembly)は、型SomeTypeInAssemblyFooを含むアセンブリFooをロードします。

3)単純なものではありません。 Reflection APIまたはRoslyn APIを使用してすべての参照を列挙し、それぞれをロードすることができます。

説明が明確でない場合や詳細を知りたい場合は、お気軽にご質問ください。

+0

優れた回答、+1! – GETah

関連する問題