1

CSharpCodeProvider を使用して、C# コードを介した統合スクリプトを可能にするアプリケーションがあります。スクリプトは、動的に放出されたアセンブリを参照できます (これらは IL Emit によって作成されます)。この参照を可能にするために、動的に生成されたアセンブリをディスク上のファイルに保存し、この場所を CompilerParameters.ReferencedAssemblies コレクションに追加します。

これは、スクリプトの最初のコンパイルと実行では問題なく機能します。スクリプトから生成されたクラスをインスタンス化するコードがあります。これにはパラメーターを受け取るコンストラクターがあり、その一部は動的に出力されたアセンブリの型です。次のようになります。

        var hostType = _compilerResults.CompiledAssembly.GetType("ExMod.Engine.ScriptHost");

        var parameters = new List<object>();
        parameters.Add(simulation);

        var extraParameters =
            simulation.Environment.Controllers.
            Select(c => c.GetPrecompiledContext()).
            Where(c => c != null);
        parameters.AddRange(extraParameters);

        _scriptHost = (ScriptHostBase)Activator.CreateInstance(hostType, parameters.ToArray());

extraParameters 式は、外部の動的に生成された型への参照が追加される場所です。

スクリプトをもう一度コンパイルして実行しようとすると、問題が発生します。これは、新しいバージョンの IL Emit アセンブリも再発行した場合にのみ発生します。例外は Activator.CreateInstance 呼び出しで発生し、次のとおりです。

MissingMethodException: Constructor on type 'ExMod.Engine.ScriptHost' not found.

所見:

  1. デバッガーを介して、正しいパラメーターを持つコンストラクターが存在することを確認しました。
  2. また、(デバッガーで Make Object ID を使用して) コンストラクターの 'Controller' パラメーター (動的に発行されたアセンブリから参照される型) が、ほとんどの動的アセンブリではなく、元の動的アセンブリを参照しているため、問題が発生していることを確認しました。最近発行された動的アセンブリ。これが、型が一致せず、コンストラクターが解決されない理由です。
  3. CSharpCodeProvider コンパイラを実行してからスクリプトを実行しようとすると、AppDomain AssemblyResolve イベントが呼び出されません。このイベントには、常に「最新の」動的アセンブリに解決する特別なロジックがあります。

私の理論では、どういうわけか CSharpCodeProvider が「最新」ではなく「最も古い」動的アセンブリを解決しているということです。これは、両方の名前と場所が同じであるために発生します。質問: CSharpCodeProvider を動的アセンブリの最新バージョンに解決するにはどうすればよいですか?

動的に生成されるアセンブリごとに場所を変更することを検討しましたが、スクリプトの反復ごとにディスク上に大量のコピーを作成することは避けたいと考えています。

4

1 に答える 1

0

Emitコードでビルドごとに新しいビルド番号を作成することで、問題を解決できることを発見しました。AssemblyNameを生成するコードでこれを使用します。

        var name = new AssemblyName();
        name.Name = "AB-PLC";
        name.Version = new Version(0, 0, Interlocked.Increment(ref _buildNumber), 0);

上記の_buildNumberは、単純な静的intフィールドです。

これにより、異なるビルドのFullNameが一致しなくなったため、CSharpCodeProviderが正しいアセンブリを解決できるようになります。まだディスクにエクスポートされたアセンブリのコピーは1つだけです(各ILエミットビルドで上書きされます)。

CSharpCodeProviderがFullNameを変更せずに正しいアセンブリを解決できるかどうかを知りたいのですが、現在のところ、このソリューションで十分です。

于 2012-11-07T17:02:42.133 に答える