正在处理AppDomain.AssemblyResolve事件

本文关键字:AssemblyResolve 事件 AppDomain 处理 | 更新日期: 2023-09-27 18:22:49

在解析运行时加载的某些dll的程序集时,我正在尝试使用AppDomain.AssemblyResolve事件来处理异常(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没有那么有用。

你能给我一些变通办法吗?

有没有一种方法可以在事件被激发时向其传递一些其他参数?

正在处理AppDomain.AssemblyResolve事件

您可以从目录中定义程序集的字典,如下所示:

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事件被激发时,您没有关于导致加载的类型的信息,只有程序集名称。在这种情况下,不清楚为什么要按特定类型查找程序集。

请注意,如果两个程序集碰巧具有相同的标识(即非强签名大小写中的文件名),并且其中一个程序集已加载,则即使在已加载的程序集中找不到类型,事件也不会在预期的时间内激发。

链接到用于历史目的的文章:解析部件载荷。