问题描述
首先我需要强调的是,这与 这个线程.此外,安装 KB2468871 也无济于事.
First of all I need to emphasize that this is slightly different question than the one in this thread. Additionally, installing KB2468871 doesn't help.
我试图尽可能地简化这个问题.一般来说,它是关于使用 Assembly.LoadFile(...) 在桌面应用程序中加载 PCL 程序集.
I tried to simplify this problem as much as possible. In general it about loading PCL assemblies in Desktop application with Assembly.LoadFile(...).
假设有一个 .NET 4.0 控制台应用程序(称为C").它引用了 .NET 4.0 程序集(称为N4")和 PCL 程序集(称为PCL").
Let's say there is a .NET 4.0 Console Application (called "C"). It references .NET 4.0 assembly (called "N4") and PCL assembly (called "PCL").
其中 N4 如下所示:
where N4 looks like this:
using System.Linq;
namespace N4
{
public class ClassInN4
{
public static string Greet()
{
return new string(
"hello from N4"
.ToCharArray()
.Select(char.ToUpper)
.ToArray()
);
}
}
}
PCL 看起来像这样:
PCL looks like this:
using System.Linq;
namespace PCL
{
public class ClassInPCL
{
public static string Greet()
{
return new string(
"hello from pcl"
.ToCharArray()
.Select(char.ToUpper)
.ToArray()
);
}
}
}
和 C 看起来像这样:
and C look like this:
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);
}
}
}
}
当您运行此应用程序时,您会得到绝对正确的结果:
When you run this application you get absolutely correct results:
N4: HELLO FROM N4
PCL: HELLO FROM PCL
让我们在 Program.Main 中为 CurrentDomain 添加 AssemblyResolve 事件:
Let's add AssemblyResolve event to CurrentDomain in Program.Main:
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"文件加载它.
So, what it does if assembly cannot be found it tries to load it from ".data" file.
让我们进入应用程序文件夹并将N4.dll"重命名为N4.data"并运行C.exe".
Let's go application folder and rename "N4.dll" to "N4.data" and run "C.exe".
Probing 'C:xxxCinDebugN4.data'
N4: HELLO FROM N4
PCL: HELLO FROM PCL
因此它通过 AssemblyResolve 并最终加载N4.data"并与原始数据一样好.
So it goes through AssemblyResolve and finally loads "N4.data" and works as good as original.
让我们将N4.data"还原为N4.dll"并将PCL.dll"重命名为PCL.data"然后...
Let's revert "N4.data" to "N4.dll" and rename "PCL.dll" to "PCL.data" and...
Probing 'C:xxxCinDebugPCL.data'
N4: HELLO FROM N4
Probing 'C:xxxCinDebugSystem.Core.data'
Probing 'C:xxxCinDebugSystem.Core.data'
Probing 'C:xxxCinDebugSystem.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).
Please note that PCL assembly was loaded just fine, the problem is, it only can't find its dependencies (System.Core) anymore.
这就像 Assembly.LoadFile(fileName) is-a no-no 如果加载的程序集是可移植的.
It's like Assembly.LoadFile(fileName) is-a no-no if loaded assembly is portable.
有人遇到过这个问题吗?有没有人解决过这个问题?
Did anyone have this problem? Did anyone solved this problem?
您可以在此处找到所有文件.
You can find all files here.
感谢 leppie 强迫我检查其他选项.当我回答是的,是的,我试过"时,我实际上想确定我没有说谎.显然值得检查.
Thanks to leppie for forcing me to check other options. I actually wanted to be sure that I'm not lying while I answer "Yeah, yeah, I tried". Apparently it was worth checking.
来自 Suzanne Cook 的 .NET CLR 注释一个>:
小心 - 这些不是一回事.
LoadFrom() 通过 Fusion 并且可以重定向到不同路径但具有相同标识的另一个程序集,如果一个程序集已经加载到 LoadFrom 上下文中.LoadFile() 根本不通过 Fusion 绑定 - 加载器只是继续加载*调用者请求的内容.它不使用 Load 或 LoadFrom 上下文.
LoadFrom() goes through Fusion and can be redirected to another assembly at a different path but with that same identity if one is already loaded in the LoadFrom context. LoadFile() doesn't bind through Fusion at all - the loader just goes ahead and loads exactly* what the caller requested. It doesn't use either the Load or the LoadFrom context.
推荐答案
您可以返回您平台的 System.Core
程序集(例如 version 4.0.0.0 for .NET Framework 4.0
) 来自 AssemblyResolve
事件,当被要求提供 2.0.5.0
版本时.
You can return the System.Core
assembly of your platform (e.g. version 4.0.0.0 for .NET Framework 4.0
) from the AssemblyResolve
event, when asked for the 2.0.5.0
version.
我正在通过 Load(byte[])
加载存储为资源的所有引用程序集,这也无法解析 2.0.5.0
程序集,并且我检索了两者System
和 System.Core
来自 AppDomain.CurrentDomain.GetAssemblies()
.
I am loading all my referenced assemblies stored as resources via Load(byte[])
, which also fails to resolve the 2.0.5.0
assembly, and I retrieve both System
and System.Core
from AppDomain.CurrentDomain.GetAssemblies()
.
这篇关于“无法加载文件或程序集“System.Core,版本=2.0.5.0,..."动态加载可移植类库时的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!