整个情况有点复杂,所以请与我保持一段时间以获得上下文......假设我们有一些集会:
主应用程序通过Assembly.LoadForm()
从应用程序库外部的路径加载DerviedClass.dll程序集,并尝试通过GetTypes()
获取其类型,即
Assembly derived = Assembly.LoadFrom(@"..\otherdir\DerivedClass.dll");
Type[] foundTypes = derived.GetTypes();
如果BaseClass.dll程序集位于DerivedClass.dll旁边(两个程序集都在..\otherdir
中,则一切都按预期工作。
接下来,删除产生LoaderException的BaseClass.dll
。要获得有关此内容的更多信息,请添加AssemblyResolve Handler
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolver;
只是将请求的程序集及其版本写入控制台,即
public static Assembly AssemblyResolver(object sender, ResolveEventArgs args)
{
Console.WriteLine("Resolving " + args.Name + " from " + args.RequestingAssembly);
return null;
}
正如所料,调用AssemblyResolver时args.Name
等于BaseClass, Version=1.0.0.0, ...
。
现在,使用版本2.0.0.0重新编译BaseClass.dll并将其放到otherdir
。
由于同样奇怪的原因,这已经成功了。 DerivedClass.dll不应该期望版本1.0.0.0并且拒绝使用版本1.0.0.0吗?
此外,如果我们添加一个应用程序配置,它将BaseClass从版本1.0.0.0重定向到版本2.0.0.0,即
<dependentAssembly>
<assemblyIdentity name="BaseClass"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
并再次删除BaseClass.dll(产生LoaderException),仍然调用AssemblyResolver args.Name
等于BaseClass, Version=1.0.0.0, ...
。 至少现在版本不应该是Version=2.0.0.0
?
有人可以向我解释,为什么更改BaseClass.dll的版本不会产生错误?为什么没有使用版本2.0.0.0调用AssemblyResolver?
---编辑--- 另一个有趣的事实:如果所有程序集都具有强名称和发布者策略配置文件,则Assembly.LoadFrom仅在找到版本2.0.0.0时才有效,即使版本1.0.0.0可用且DerivedClass.dll为使用1.0.0.0版本构建。
但是,仍然使用版本1.0.0.0调用AssemblyResolver。
对我来说,当调用LoadFrom Assemblies的AssemblyResolver时,看起来似乎不应用发布者策略。这可能吗?