Подтвердить что ты не робот

Работа с событием 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, предоставленный событием, не очень полезен.

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

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

4b9b3361

Ответ 1

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

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);
}

Предоставить реализацию для hook...

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;

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

Ответ 2

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

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

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

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