Работа с AppDomain.Событие AssemblyResolve

Я пытаюсь использовать AppDomain.AssemblyResolve событие для обработки исключений при разрешении сборок некоторой dll, загруженной во время выполнения (SerializationException для динамически загружаемого типа ).

когда событие запускается, я загружаю все библиотеки DLL в свой каталог и создаю Assembly массив, затем я использую этот метод, чтобы получить Assembly содержащий тип, который я указываю:

public static Assembly GetAssemblyContainingType(String completeTypeName, 
                                                 Assembly[] assemblies)
{
    Assembly assembly = null;

    foreach (Assembly currentassembly in assemblies)
    {
        Type t = currentassembly.GetType(completeTypeName, false, true);
        if (t != null)
        {
            assembly = currentassembly;
            break;
        }
    }

    return assembly;
}

проблема в том, что этот код работает только с тегом AssemblyQualifiedName и ResolveEventArgs.Name предусмотрено событие не так уж и полезно.

можете ли вы предложить мне решение?

есть ли способ передать некоторые другие аргументы событию при его запуске?

2 ответов


вы можете определить словарь сборок из своего каталога, например:

private readonly IDictionary<string,Assembly> additional =
    new Dictionary<string,Assembly>();

загрузите этот словарь с сборками из вашего известного каталога, например:

foreach ( var assemblyName ... corresponding to DLL names in your directory... ) {
    var assembly = Assembly.Load(assemblyName);
    additional.Add(assembly.FullName, assembly);
}

обеспечить реализацию для крючка...

private Assembly ResolveAssembly(Object sender, ResolveEventArgs e) {
    Assembly res;
    additional.TryGetValue(e.Name, out res);
    return res;
}

...и подключить его к событию:

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveAssembly;
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;

это должно сделать трюк.


Если вы знаете список сборок, которые могут содержать тип, который вы планируете десериализовать, было бы лучше просто предварительно загрузить все сборки перед сериализацией.

при запуске события AssemblyResolve у вас нет информации о том, какой тип вызвал загрузку, а только имя сборки. Непонятно, почему в этом случае вы будете искать сборку по какому-то конкретному типу.

обратите внимание, что если 2 сборки имеют одинаковый идентификатор (т. е. имя файла в non-strongly-signed case), и одно уже загруженное событие не будет срабатывать, когда вы ожидаете, даже если тип не найден в уже загруженной сборке.

ссылка на статью в исторических целях: Разрешение Сборочных Нагрузок.