5

Roslyn ベースのスクリプト エンジンをアプリケーションに埋め込んでいますが、いくつかの問題に直面し始めました。私のエンジンに参照をロードするとき、私は次のことを行います

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

質問:

  1. アセンブリが他のアセンブリを参照している場合MyAssemblyLocation、Roslyn にアセンブリを実行せずに読み込むように指示するにはどうすればよいですか?engine.AddReference("MyAssemblyLocation");
  2. スクリプトが実行されるはずのホスト アプリケーションは、スクリプトで使用したいいくつかのアセンブリを既に読み込んでいます。Roslyn がメモリ内の既に読み込まれている dll にフックし、新しいインスタンスを読み込まない方法はありますか?
  3. 最後に、Roslyn にすべての依存関係を再帰的にロードするように指示する方法はありますか?MyAssemblyLocation

ありがとうございました。

4

1 に答える 1

6

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

詳細:C#コンパイラは、依存ファイルがどこにあるかを推測しません。アセンブリファイルは、そのすべての依存関係へのフルパスを指定していません。それらの名前のみが含まれており、通常、コンパイラがアセンブリファイルを見つけるには十分ではありません。

詳細:2種類の依存関係があります。それらをコンパイル時の依存関係(a)と実行時の依存関係(b)と呼びます。

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

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

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

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

説明が明確でない場合、または詳細を知りたい場合は、遠慮なく質問してください。

于 2012-11-19T19:30:05.303 に答える