Working with AppDomain.AssemblyResolve event

[亡魂溺海] 提交于 2019-12-17 06:51:50

问题


I'm trying to use AppDomain.AssemblyResolve event to handle exceptions while resolving Assemblies of some dll loaded at runtime (SerializationException for dynamically loaded Type).

When the event is fired, I load all DLLs in my directory and create an Assembly array, then I use this method to get the Assembly containing the type I specify:

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

The problem is that this code works only with an AssemblyQualifiedName, and the ResolveEventArgs.Name provided by the event is not so useful.

Can you suggest me some workaround?

Is there a way to pass some other arguments to the event when it is fired?


回答1:


You can define a dictionary of the assemblies from your directory, like this:

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

Load this dictionary with the assemblies from your known directory, like this:

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

Provide an implementation for the hook...

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

...and hook it up to the event:

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

This should do the trick.




回答2:


If you know list of assemblies that may contain type you are planning to deserialize it could be better to simply pre-load all assemblies before doing serialization.

When AssemblyResolve event is fired you have no information about what type caused the load, but only assembly name. It is unclear why you would look up assembly by some particular type in this case.

Note that if 2 assemblies happen to have the same identity (i.e. file name in non-strongly-signed case) and one is already loaded event will not fire when you expect even if type is not found in already loaded assembly.

Link to the article for historical purposes: Resolving Assembly Loads.



来源:https://stackoverflow.com/questions/9180638/working-with-appdomain-assemblyresolve-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!