41

他のアセンブリのものを使用するクラス ライブラリを作成する場合、それらの他のアセンブリをある種のリソースとしてクラス ライブラリ内に埋め込むことは可能ですか?

つまり、 MyAssembly.dll 、SomeAssembly1.dllSomeAssembly2.dllをファイル システムに配置する代わりに、他の 2 つのファイルがMyAssembly.dllにバンドルされ、そのコードで使用できるようになります。


また、.NET アセンブリが.dllファイルである理由についても少し混乱しています。この形式は .NET より前に存在しませんでしたか? すべての .NET アセンブリは DLL ですが、すべての DLL が .NET アセンブリであるとは限りませんか? 同じファイル形式やファイル拡張子を使用するのはなぜですか?

4

8 に答える 8

59

ILMerge はアセンブリをマージします。たとえば、問題のアセンブリが厳密な名前のアセンブリであり、そのキーを持っていない場合、その署名を壊さずに ILMerge を実行することはできません。つまり、複数のアセンブリをデプロイする必要があります。

ilmerge の代わりに、1 つ以上のアセンブリをリソースとして exe または DLL に埋め込むことができます。次に、実行時にアセンブリが読み込まれるときに、埋め込まれたアセンブリをプログラムで抽出し、読み込んで実行できます。難しそうに聞こえますが、定型コードが少しだけあります。

これを行うには、他のリソース (画像、翻訳ファイル、データなど) を埋め込む場合と同様に、アセンブリを埋め込みます。次に、実行時に呼び出される AssemblyResolver を設定します。スタートアップ クラスの静的コンストラクターで設定する必要があります。コードは非常に単純です。

    static NameOfStartupClassHere()
    {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
    }

    static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
    {
        Assembly a1 = Assembly.GetExecutingAssembly();
        Stream s = a1.GetManifestResourceStream(args.Name);
        byte[] block = new byte[s.Length];
        s.Read(block, 0, block.Length);
        Assembly a2 = Assembly.Load(block);
        return a2;
    }

ResolveEventArgs パラメーターの Name プロパティは、解決するアセンブリの名前です。この名前は、ファイル名ではなく、リソースを参照します。「MyAssembly.dll」という名前のファイルを埋め込み、埋め込まれたリソースを「Foo」と呼ぶ場合、ここで必要な名前は「Foo」です。しかし、それは紛らわしいので、リソースの名前にはアセンブリのファイル名を使用することをお勧めします。アセンブリを適切に埋め込んで名前を付けた場合は、アセンブリ名を使用して GetManifestResourceStream() を呼び出すだけで、アセンブリをそのようにロードできます。とてもシンプルです。

これは、単一の組み込みアセンブリと同様に、複数のアセンブリでも機能します。

実際のアプリでは、そのルーチンでより良いエラー処理が必要になります。たとえば、指定された名前のストリームがない場合はどうでしょうか? 読み取りが失敗した場合はどうなりますか? などしかし、それはあなたに任せています。

アプリケーション コードの残りの部分では、通常どおりアセンブリの型を使用します。

アプリをビルドするときは、通常どおり、問題のアセンブリへの参照を追加する必要があります。コマンド ライン ツールを使用する場合は、csc.exe で /r オプションを使用します。Visual Studio を使用する場合は、プロジェクトのポップアップ メニューで [参照の追加...] を行う必要があります。

実行時に、アセンブリのバージョン チェックと検証は通常どおり機能します。

唯一の違いは分布にあります。アプリを展開または配布するときに、埋め込まれた (および参照された) アセンブリの DLL を配布する必要はありません。メイン アセンブリをデプロイするだけです。他のアセンブリはメインの DLL または EXE に組み込まれているため、配布する必要はありません。

于 2009-03-09T05:27:20.253 に答える
35

アセンブリをマージするためのILMergeを見てください。

また、.NET アセンブリが .dll ファイルである理由についても少し混乱しています。この形式は .NET より前に存在しませんでしたか?

はい。

すべての .NET アセンブリ DLL は、

通常は DLL または EXE のいずれかですが、netmodule にすることもできます。

しかし、すべての DLL が .NET アセンブリであるとは限りませんか?

正しい。

同じファイル形式やファイル拡張子を使用するのはなぜですか?

なぜ違うのか - それは同じ目的を果たします!

于 2008-10-21T17:11:05.417 に答える
8

アセンブリ (または実際には任意のファイル) をリソースとして埋め込むことができResourceManagerます (そして、クラスを使用してそれらにアクセスします) が、アセンブリを結合するだけの場合は、ILMergeなどのツールを使用することをお勧めします。

EXE および DLL ファイルはWindows ポータブル実行可能ファイルであり、.NET コードを含む将来のタイプのコードに対応するのに十分な汎用性があります (これらは DOS でも実行できますが、DOS では実行できないというメッセージのみが表示されます)。.NET ランタイムがまだ実行されていない場合に起動する手順が含まれています。1 つのアセンブリが複数のファイルにまたがることもありますが、ほとんどの場合ではありません。

于 2008-10-21T17:11:24.807 に答える
5

注 ILMerge は XAML などの埋め込みリソースでは機能しないため、WPF アプリなどは Cheeso のメソッドを使用する必要があります。

于 2009-05-13T22:51:13.760 に答える
4

Mono プロジェクトが提供する mkbundle ユーティリティもあります。

于 2008-10-21T17:19:42.810 に答える
1

同じファイル形式やファイル拡張子を使用するのはなぜですか?

なぜ違うのか - それは同じ目的を果たします!

ここで私の 2¢ の説明: DLL はダイナミック リンク ライブラリです。古いスタイルの .dll (C コード) と .net スタイルの .dll はどちらも、定義上、「ダイナミック リンク」ライブラリです。したがって、.dll は両方の適切な説明です。

于 2012-12-10T19:53:44.523 に答える
0

アセンブリをリソースとして埋め込み、AssemblyResolve イベント ハンドラーを使用して Load(byte[]) オーバーロードを使用して動的にロードするという Cheeso の回答に関しては、ロードするアセンブリの既存のインスタンスの AppDomain をチェックするようにリゾルバーを変更する必要があります。既に読み込まれている場合は、既存のアセンブリ インスタンスを返します。

そのオーバーロードを使用して読み込まれたアセンブリにはコンテキストがないため、フレームワークがアセンブリを複数回再読み込みしようとする可能性があります。既に読み込まれているインスタンスを返さないと、フレームワークが 2 つの異なるアセンブリからのものであると見なすため、等しいはずの同じアセンブリ コードと型の複数のインスタンスになる可能性があります。

「コンテキストなし」にロードされた同じアセンブリに対して複数の AssemblyResolve イベントが作成される少なくとも 1 つの方法は、AppDomain にロードされた複数のアセンブリから公開される型への参照がある場合です。これらの型を解決する必要があるコードが実行されるためです。

https://msdn.microsoft.com/en-us/library/dd153782%28v=vs.110%29.aspx

リンクからのいくつかの顕著な点:

「AppDomain.AssemblyResolveイベントを処理しない限り、他のアセンブリはコンテキストなしで読み込まれたアセンブリにバインドできません」

「コンテキストなしで同じ ID を持つ複数のアセンブリを読み込むと、同じ ID を持つアセンブリを複数のコンテキストに読み込むことによって引き起こされるものと同様の型 ID 問題が発生する可能性があります。アセンブリを複数のコンテキストに読み込まないようにするを参照してください。」

于 2016-01-14T22:52:21.897 に答える