LoaderOptimization.MultiDomain заставляет AssemblyResolve не запускаться
У меня есть некоторые проблемы, как только LoaderOptimization.MultiDomain
включен. Почему-то больше не запускается событие AssemblyResolve, когда сборка не найдена в некоторых конкретных сценариях.
Я сузил его до случая с двумя проектами. Вы можете скачать полное решение здесь: https://developercommunity.visualstudio.com/storage/attachments/24787-appdomainresolvetest.zip
Допустим, у меня есть программа высшего уровня:
class AppProgram
{
// Comment this and both Resolve1 and Resolve2 will happen
// If enabled, Resolve2 doesn't happen
[LoaderOptimization(LoaderOptimization.MultiDomain)]
static void Main(string[] args)
{
var applicationPath = AppDomain.CurrentDomain.BaseDirectory;
var appDomainSetup = new AppDomainSetup { ApplicationBase = Directory.GetParent(applicationPath).FullName };
var otherDomain = AppDomain.CreateDomain("other domain", AppDomain.CurrentDomain.Evidence, appDomainSetup);
otherDomain.DoCallBack(TestCallback);
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Console.WriteLine($"Resolve1 {args.Name}");
return null;
}
private static void TestCallback()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
var remoteAssembly = AppDomain.CurrentDomain.Load("ConsoleApplication1");
remoteAssembly.EntryPoint.Invoke(null, new object[] { new string[0] });
}
}
Затем сборка ConsoleApplication1 имеет следующий код:
(Обратите внимание, что ссылка на Newtonsoft.Json (w/ NuGet) имеется, но для параметра "Локальное копирование" задано значение "false", что приводит к преднамеренному разрешению сборки и исключению FileNotFoundException)
class ConsoleProgram
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
try
{
Test();
}
catch (FileNotFoundException)
{
}
}
private static void Test()
{
JsonConvert.SerializeObject(true);
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Console.WriteLine($"Resolve2 {args.Name}");
return null;
}
}
Что происходит, если LoaderOptimization.MultiDomain
атрибут не установлен на Main, вызываются и Resolve1 (из программы верхнего уровня), и Resolve2 (из библиотеки). Однако, как только LoaderOptimization.MultiDomain
установлено, вызывается только Resolve1.
В моем реальном приложении MultiDomain очень важен, чтобы избежать JIT и снова инициализировать сборки (сократить время запуска с 5 секунд практически до нуля). В результате я хотел бы понять причину этой ошибки и, надеюсь, найти обходной путь.
Редактировать: даже при попытке жесткого кодирования моего разрешения во время Resolve1 кажется, что он не может кэшировать сборки (загрузка идет медленно). Может быть, MultiDomain работает только для сборок в ApplicationBase
? В этом случае, я полагаю, мне придется использовать PrivateBinPath для оптимизации JIT. Хотелось бы узнать, можно ли устранить ошибку AssemblyResolve, потому что еще есть несколько дополнительных сборок, загруженных по внешнему пути, и мне все равно, если они не являются JIT.