Assembly.LoadFromとAssembly.Loadを使用してアセンブリの読み込みを混合するときの奇妙な動作
-
03-07-2019 - |
質問
Assembly.LoadFromとAssembly.Loadを使用してアセンブリの読み込みを混合するときの奇妙な動作
Assembly.LoadFrom以降でAssembly.Loadを使用してアセンブリをロードすると、奇妙な動作が発生しました。
Assembly.LoadFromを使用してアセンブリを読み込みます。アセンブリは、実行フォルダーではないフォルダーにあります。
テストコードでこのアセンブリを再度Assembly.Loadでロードしようとすると、System.IO.FileNotFoundExceptionでロードが失敗します(“ファイルまたはアセンブリをロードできませんでした…&#8221 ;)アセンブリが既にロードされているという事実にもかかわらず。厳密な名前と厳密でない名前の両方でロードが失敗します(このアセンブリを再度ロードする元の理由は、BinaryFormatterの使用です)。
ただし、アセンブリが実行フォルダーにある場合は、どちらの場合も、厳密な名前と厳密でない名前を使用した後の読み込みが成功します。この場合、2つの異なる場所から2つの同一のアセンブリがロードされていることがわかります。
この問題を再現する簡単なコードサンプル–
Assembly assembly1 = Assembly.LoadFrom(@" C:\ a.dll");
//厳密な名前でのロードが失敗する アセンブリassembly2 = Assembly.Load(@" a、Version = 1.0.0.0、 Culture = neutral、PublicKeyToken = 14986c3f172d1c2c");
//また、強力ではないものでのロードが失敗する アセンブリassembly3 = Assembly.Load(@" a");
- CLRが既にロードされたアセンブリを無視する理由の説明
- どのようにしてこの問題を軽減することができますか?
ありがとう。
解決
それは変ではありません。ドキュメントによると、LoadおよびLoadFromを使用して読み込むと、アセンブリが異なるコンテキストに配置されます。 これが役立つ場合があります。
- CLRが既にロードされたアセンブリを無視する理由の説明
異なるコンテキストにいるため。
- どのようにしてこの問題を軽減することができますか?
同じコンテキストから読み込むか、おそらく AppDomain.AssemblyResolve
にハンドラをアタッチすることで、CLRがアセンブリを見つけるのを助けます。
代替
アセンブリをロードする場所がAppDomain.BaseDirectoryの下のサブフォルダーである場合は、App.configにエントリを追加するだけです:
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>
他のヒント
@Kent Boogart: それが正しい説明のようです。完全な説明については、Suzanne Cookがこのブログ投稿で、あなたが投稿したオリジナルのものよりも少し詳しく説明しています。 http://blogs.msdn.com/suzcook/archive/2003 /05/29/57143.aspx
以下はAppDomain.AssemblyResolveを活用するコードです-
// register to listen to all assembly resolving attempts:
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
// Check whether the desired assembly is already loaded
private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) {
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies) {
AssemblyName assemblyName = assembly.GetName();
string desiredAssmebly = args.Name;
if (assemblyName.FullName == desiredAssmebly) {
return assembly;
}
}
// Failed to find the desired assembly
return null;
}