“动态加载可移植类库时无法加载文件或程序集’System.Core,Version = 2.0.5.0,…”exception

首先,我需要强调的是,这个问题与这个post中的问题略有不同。 此外,安装KB2468871没有帮助。

我试图尽可能地简化这个问题。 一般来说,它是关于使用Assembly.LoadFile(…)在Desktop应用程序中加载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 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中将AssemblyResolve事件添加到CurrentDomain:

 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备注 :

小心 – 这些不是一回事。

LoadFrom()通过Fusion进行转换,可以重定向到另一个不同路径的程序集,但如果已经在LoadFrom上下文中加载了相同的标识。 LoadFile()根本没有通过Fusion绑定 – 加载器只是继续并正好加载*调用者请求的内容。 它不使用Load或LoadFrom上下文。

当要求2.0.5.0版本时,您可以从AssemblyResolve事件返回平台的System.Core程序集(例如, version 4.0.0.0 for .NET Framework 4.0 )。

我通过Load(byte[])存储为资源的所有引用程序集,它也无法解析2.0.5.0程序集,我从AppDomain.CurrentDomain.GetAssemblies()检索SystemSystem.Core

我认为你得到这些问题是因为:

您收到exception是因为您没有获得最新的.NET更新。

http://www.paraesthesia.com/archive/2013/01/21/using-portable-class-libraries-update-net-framework.aspx

记下WSUS部分 – 您可能认为自己拥有最新的更新,但不会导致您的WSUS服务器过时。

这个补丁可能有所帮助,但你最好只是获取所有的.net更新:

http://support.microsoft.com/kb/2468871

(来自上面的评论)

尝试LoadFrom(…)而不是LoadFile(…)/ Load(byte []),看看是否能解决您的问题? 🙂

我遇到了同样的问题,最终得到了以下解决方案:在动态加载PCL程序集之前调用以下代码。

 Assembly.Load("System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes"); Assembly.Load("System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes"); 

如果在加载PCL程序集时缺少任何其他依赖项,则只需在上面的代码中添加一行。 出于某些奇怪和不可理解的原因,它有效。