我尝试尽可能简化这个问题。通常情况下,它涉及使用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's .NET CLR Notes:
注意 - 这两个不是同一件事情。
LoadFrom() 通过 Fusion 进行加载,如果在 LoadFrom 上下文中已经加载了具有相同标识的另一个程序集,则可以将其重定向到另一个路径上的程序集。 LoadFile() 根本不会通过 Fusion 绑定 - 加载程序就会直接加载调用者请求的内容。它不使用 Load 或 LoadFrom 上下文。
Assembly.LoadFrom
或将其作为字节数组加载吗? - leppie