1

私は、dll (埋め込みリソース) を exe に埋め込む手法を使用し、次のコードを使用して実行時に不明な dll を解決しています。

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    String resourceName = "Project.lib." + new AssemblyName(args.Name).Name + ".dll";

    using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
    {
        Byte[] assemblyData = new Byte[stream.Length];
        stream.Read(assemblyData, 0, assemblyData.Length);
        return Assembly.Load(assemblyData);
    }
};

ただし、Spark View Engine dll (たとえば) を埋め込むと、失敗します。ただし、特定の 1 か所だけです。Spark 自体は、その場で動的にクラスを生成します。これらのクラスは、Spark (using Sparkなど) を参照します。この時点で、次のエラーが発生します。

タイプ 'Spark.Class' は、参照されていないアセンブリで定義されています。アセンブリ「Spark」への参照を追加する必要があります

これは、Spark ビュー エンジンとは関係なく、動的に生成されたクラス内から埋め込まれたアセンブリを参照することに関係していると確信しています。

更新:スタックトレース

プロジェクト タスク メッセージの実行中に例外が発生しました: Spark.Compiler.BatchCompilerException: 動的ビューのコンパイルに失敗しました。c:\Users\Adam\AppData\Local\Temp\kdsjyhvu.0.cs(6,14): エラー CS0012: 型 'Spark.AbstractSparkView' は、参照されていないアセンブリで定義されています。Spark.Compiler.CSharp の Spark.Compiler.BatchCompiler.Compile(Boolean debug, String languageOrExtension, String[] sourceCode) で、アセンブリ 'Spark, Version=1.5.0.0, Culture=neutral, PublicKeyToken=7f8549eed921a12c' への参照を追加する必要があります。 .CSharpViewCompiler.CompileView(IEnumerable1 viewTemplates, IEnumerable1 allResources) at Spark.SparkViewEngine.CreateEntryInternal(SparkViewDescriptor descriptor, Boolean compile) at Spark.SparkViewEngine.CreateEntry(SparkViewDescriptor descriptor) at Spark.SparkViewEngine.CreateInstance(SparkViewDescriptor descriptor) at ProjectTasks.Core.Templater.Populate(String templateFilePath, Object data) ) \ProjectTasks\Core\Templater.cs:33 行目 ProjectTasks..Core.EmailTemplates.RenderImpl(String name, Object data) in \ProjectTasks\Core\EmailTemplates.cs:19 行目 ProjectTasks.Tasks.EmailUsersWithIncompleteModules.Run( ) \ProjectTasks\Tasks\EmailUsersWithIncompleteModules.cs: 41 行目 \ProjectTasks.MaintenanceTaskRunner.Run(Boolean runNow, IMaintenanceTask[] tasks) の \ProjectTasks\MaintenanceTaskRunner.cs: 25 行目 ProjectTasks.Initialiser.\ProjectTasks\Initialiser.cs:line 30 の Init(String[] args)

実際に解決策がある場合、解決策について何か考えはありますか?

4

3 に答える 3

2

Spark は動的コード生成に CodeDom を使用していると思います。CSharpCodeProvider は内部でソース コードを生成し、csc.exe を実行して新しい型を取得します。csc.exe は参照として物理ファイルを必要とするため、AssemblyResolve トリックはこの場合役に立ちません。

于 2011-06-12T10:21:47.373 に答える
1

スタック トレースは、Spark が System.CodeDom を使用してアセンブリを動的に生成していることを強く示唆しています。これには、参照アセンブリがディスク上のファイルである必要があり、C# コンパイラはアウトプロセスで実行されます。EXE と同じディレクトリに Spark.dll があるため、これは通常は問題になりません。

これを機能させることはできません。

Fwiw: この手法は、システム リソースをひどく浪費します。アセンブリに必要なメモリ量が 2 倍になります。これは高価な種類のメモリでもあり、プロセス間で共有できず、アセンブリ ファイルではなくページング ファイルによってサポートされます。また、重大な型識別の問題を自分で購入することもできます。.NET は、単一ファイルでの展開を既にサポートしています。それはsetup.exeと呼ばれます

于 2011-06-12T12:58:09.450 に答える
0

他の人が言ったように、問題は、CodeDom がディスク上にアーティファクトを生成し、後でビューをレンダリングするためにアクセスする必要があるという事実にあります。

いずれにせよ、Spark を埋め込むとメモリを大量に消費する可能性があるという事実は別として、この問題には潜在的な解決策があると思います。問題がその場での動的ビュー生成によって引き起こされているという事実を考えると、Spark のバッチ コンパイルオプションを利用して、ビルドの一部としてビューの dll を生成してみませんか。

これを実現するには、次のようなコードを使用できます。

var factory = new SparkViewFactory(settings)
               {
                   ViewFolder = new FileSystemViewFolder(viewsLocation)
               };

// And generate all of the known view/master templates into the target assembly
var batch = new SparkBatchDescriptor(targetPath);

factory.Precompile(batch);

最後に、コンパイルされたビューを含む出力 dll が必要です。その後、メインの Spark.dll を埋め込むのと同じ方法でその dll を埋め込むことができます。


ロブに役立つことを願っています

于 2011-06-13T17:53:44.457 に答える