"Не удалось загрузить файл или сборку" System.Core, Version = 2.0.5.0,... "при загрузке Portable Class Library динамически
Прежде всего, мне нужно подчеркнуть, что это немного другой вопрос, чем вопрос в этой теме. Кроме того, установка KB2468871 не помогает.
Я попытался максимально упростить эту проблему. В общем, о загрузке сборок PCL в приложении Desktop с Assembly.LoadFile(...).
Скажем, есть консольное приложение .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
Добавьте дополнение AssemblyResolve к CurrentDomain в 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".
Отпустите папку приложения и переименуйте "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) - нет-нет, если загруженная сборка переносима.
У кого-нибудь была эта проблема? Кто-нибудь решил эту проблему?
Вы можете найти все файлы здесь.
EDIT:
Благодаря leppie заставляет меня проверять другие варианты. Я действительно хотел быть уверенным, что я не вру, пока я отвечаю: "Да, да, я пытался". По-видимому, стоит проверить.
От Заметки CLR для Suzanne Cook.NET:
Будьте осторожны - это не одно и то же.
LoadFrom() проходит через Fusion и может быть перенаправлен на другую сборку по другому пути, но с тем же идентификатором, если он уже загружен в контексте LoadFrom. LoadFile() вообще не связывается с Fusion - загрузчик просто идет вперед и точно загружает * то, что запросил вызывающий. Он не использует контекст Load или LoadFrom.
Ответы
Ответ 1
Вы можете вернуть System.Core
сборку вашей платформы (например, version 4.0.0.0 for .NET Framework 4.0
) из события AssemblyResolve
при запросе версии 2.0.5.0
.
Я загружаю все мои ссылочные сборки, хранящиеся в виде ресурсов через Load(byte[])
, также не удается разрешить сборку 2.0.5.0
, и я извлекаю как System
, так и System.Core
из AppDomain.CurrentDomain.GetAssemblies()
.
Ответ 2
Я думаю, что вы получаете эти проблемы, потому что:
Вы получаете исключение, потому что у вас нет последних обновлений .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 []) и посмотрите, устраняет ли это вашу проблему?:)
Ответ 3
У меня была такая же проблема, и я получил следующее решение: вызовите следующий код перед динамической загрузкой сборки 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, вам просто нужно добавить строку в код выше.
По какой-то странной и непонятной причине это работает.