まず、これはこのスレッドの質問とは少し異なることを強調する必要があります。さらに、KB2468871をインストールしても役に立ちません。
この問題をできるだけ単純化しようとしました。一般に、Assembly.LoadFile(...) を使用してデスクトップ アプリケーションに PCL アセンブリをロードすることについてです。
.NET 4.0 コンソール アプリケーション (「C」と呼ばれる) があるとします。.NET 4.0 アセンブリ (「N4」と呼ばれる) および PCL アセンブリ (「PCL」と呼ばれる) を参照します。
N4 は次のようになります。
using System.Linq;
namespace N4
{
public class ClassInN4
{
public static string Greet()
{
return new string(
"hello from N4"
.ToCharArray()
.Select(char.ToUpper)
.ToArray()
);
}
}
}
PCL は次のようになります。
using System.Linq;
namespace PCL
{
public class ClassInPCL
{
public static string Greet()
{
return new string(
"hello from pcl"
.ToCharArray()
.Select(char.ToUpper)
.ToArray()
);
}
}
}
C は次のようになります。
using System;
using System.IO;
using System.Reflection;
using N4;
using PCL;
namespace C
{
internal class Program
{
private static void Main(string[] args)
{
Test();
Console.ReadLine();
}
private static void Test()
{
Test("N4", ClassInN4.Greet);
Test("PCL", ClassInPCL.Greet);
}
private static void Test(
string title,
Func<string> generator)
{
try
{
Console.WriteLine(
"{0}: {1}", title, generator());
}
catch (Exception e)
{
Console.WriteLine(
"{0}: {1} -> {2}", title, e.GetType(), e.Message);
}
}
}
}
このアプリケーションを実行すると、完全に正しい結果が得られます。
N4: HELLO FROM N4
PCL: HELLO FROM PCL
Program.Main の CurrentDomain に AssemblyResolve イベントを追加しましょう。
AppDomain.CurrentDomain.AssemblyResolve += (_, a) => {
var fileName = Path.GetFullPath(
new AssemblyName(a.Name).Name + ".data");
Console.WriteLine("Probing '{0}'", fileName);
return
File.Exists(fileName)
? Assembly.LoadFile(fileName)
: null;
};
したがって、アセンブリが見つからない場合、「.data」ファイルからロードしようとします。
アプリケーション フォルダに移動し、「N4.dll」を「N4.data」に名前変更して、「C.exe」を実行します。
Probing 'C:\xxx\C\bin\Debug\N4.data'
N4: HELLO FROM N4
PCL: HELLO FROM PCL
そのため、AssemblyResolve を通過し、最終的に「N4.data」をロードして、オリジナルと同じように機能します。
「N4.data」を「N4.dll」に戻し、「PCL.dll」の名前を「PCL.data」に変更して...
Probing 'C:\xxx\C\bin\Debug\PCL.data'
N4: HELLO FROM N4
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
Probing 'C:\xxx\C\bin\Debug\System.Core.data'
PCL: System.IO.FileNotFoundException -> Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The system cannot find the file specified.
PCL アセンブリが正常に読み込まれたことに注意してください。問題は、依存関係 (System.Core) しか見つからないことです。
ロードされたアセンブリが移植可能である場合、 Assembly.LoadFile(fileName) はノーノーのようです。
誰かがこの問題を抱えていましたか?誰かがこの問題を解決しましたか?
ここですべてのファイルを見つけることができます。
編集: 他のオプションをチェックするように強制してくれたleppieに感謝します。「ええ、ええ、試しました」と答える間、私は実際に嘘をついていないことを確認したかった. どうやらそれはチェックする価値がありました。
Suzanne Cook の .NET CLR Notesから:
注意してください - これらは同じものではありません。
LoadFrom() は Fusion を通過し、別のパスにある別のアセンブリにリダイレクトできますが、LoadFrom コンテキストに既に読み込まれている場合は同じ ID でリダイレクトできます。LoadFile() は Fusion を介してまったくバインドしません。ローダーは先に進み、呼び出し元が要求したものを正確に*ロードします。Load コンテキストも LoadFrom コンテキストも使用しません。