我正在尝试通过挂钩进入AppDomain.AssemblyResolve
和AppDomain.ReflectionOnlyAssemblyResolve
事件加载一些模块。虽然我让前者工作,但我对后者失败了。我把问题归结为这个小程序:
public static class AssemblyLoader
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve +=
ReflectionOnlyAssemblyResolve;
// fails with FileNotFoundException
Assembly.ReflectionOnlyLoad("Foo");
}
public static Assembly ReflectionOnlyAssemblyResolve(object sender,
ResolveEventArgs args)
{
Trace.TraceInformation(
"Failed resolving Assembly {0} for reflection", args.Name);
return null;
}
}
在尝试使用FileNotFoundException
时,运行此程序会失败并使用Assembly.ReflectionOnlyLoad
,但它不会调用ReflectionOnlyAssemblyResolve处理程序。我很难过。
有没有人知道这可能是什么原因以及如何让它发挥作用?
谢谢!
看起来ReflectionOnlyAssemblyResolve事件仅用于解析依赖关系,而不是顶级程序集,如下所示:
http://codeidol.com/csharp/net-framework/Assemblies,-Loading,-and-Deployment/Assembly-Loading/
和这里:
http://blogs.msdn.com/junfeng/archive/2004/08/24/219691.aspx
扩展了casperOne的答案。
如果要拦截直接的Assembly Resolve事件,则需要挂钩到AppDomain.AssemblyResolve事件。这是一个全球性的钩子,但它不适合你的场景。但是,如果您的应用程序是单线程的,则可以进行短期连接以拦截特定的解析事件。
static void LoadWithIntercept(string assemblyName) {
var domain = AppDomain.CurrentDomain;
domain.AssemblyResolve += MyInterceptMethod;
try {
Assembly.ReflectionOnlyLoad(assemblyName);
} finally {
domain.AssemblyResolve -= MyInterceptMethod;
}
}
private static Assembly MyInterceptMethod(object sender, ResolveEventArgs e) {
// do custom code here
}
您可以通过调用程序集上的ExportedTypes来强制它,如下所示:
var dummy = asm.ExportedTypes;
因此,如果要以递归方式加载包含其所有引用的程序集:
private void _forceAssemblyResolve(Assembly asm) { var dummy = asm.ExportedTypes; }
var result= Assembly.ReflectionOnlyLoad("Foo");
_forceAssemblyResolve(result);
public static Assembly ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
{
var childAssembly = _resolve(args);
_forceAssemblyResolve(childAssembly);
}