C# 使用 AppDomain.AssemblyResolve 事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9180638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Working with AppDomain.AssemblyResolve event
提问by davioooh
I'm trying to use AppDomain.AssemblyResolveevent to handle exceptions while resolving Assemblies of some dll loaded at runtime (SerializationException for dynamically loaded Type).
我正在尝试使用AppDomain.AssemblyResolve事件来处理异常,同时解析在运行时加载的某些 dll 的程序集(动态加载类型的 SerializationException)。
When the event is fired, I load all DLLs in my directory and create an Assemblyarray, then I use this method to get the Assemblycontaining the type I specify:
当事件被触发时,我加载目录中的所有 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;
}
The problem is that this code works only with an AssemblyQualifiedName, and the ResolveEventArgs.Nameprovided by the event is not so useful.
问题是此代码仅适用于AssemblyQualifiedName,而ResolveEventArgs.Name事件提供的 并不是那么有用。
Can you suggest me some workaround?
你能给我建议一些解决方法吗?
Is there a way to pass some other arguments to the event when it is fired?
有没有办法在事件被触发时将其他一些参数传递给事件?
采纳答案by dasblinkenlight
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.
这应该可以解决问题。
回答by Alexei Levenkov
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.
当 AssemblyResolve 事件被触发时,您没有关于导致加载的类型的信息,而只有程序集名称。在这种情况下,不清楚为什么要按某种特定类型查找程序集。
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.
请注意,如果 2 个程序集碰巧具有相同的标识(即非强签名情况下的文件名)并且一个已加载事件将不会在您期望时触发,即使在已加载的程序集中未找到类型。
Link to the article for historical purposes: Resolving Assembly Loads.
出于历史目的链接到文章:解决装配负载。

