最近同事遇到一个问题,关于程序需要在动态的时候决定究竟要加载dll的哪个版本.
我们程序现在依赖于cad的一个simple.dll. cad有2004,有2006.这个simple.dll是强命名的,04跟06虽不同但版本号是一样的,不可以放在同一目录下.我们现在的程序需要同时支持cad 2004,2006.当客户端安装的是Cad2004时我们要用04的simple.dll功能,安装的是cad2006时,使用06的simple.dll.
我们知道.net提供了一种机制可以保证使用最新版本的dll或者由用户决定想用哪个版本.具体可见 How the Runtime Locates Assemblies.但是这种方案主要用于解决多个版本的问题,明显跟我们遇到的情况有点不同.而且此种方法是由config文件决定的,实际上也是达不到运行时决定加载哪个版本,只能事先配置config文件.
那么想到的另一种方法就是动态加载.然而动态加载在编译期丧失了类型透明的好处,只能通过Invoke去调用方法.现在需要大量调用simple.dll里的方法,需要额外做的事情就太多了.
今天在看 蝈蝈俊的:使用VS2005的 ClickOnce 技术实现按需下载组件得到启示,并且尝试后证明是可行了.
首先我们照样直接add reference "simple.dll",该干嘛就干嘛.
然后我们制造事故,在程序的目录下不放置simple.dll(设置Copy Local 属性false即可),让CLR加载程序集失败,并触发AssemblyResolve 事件,然后我们在此事件里动态加载simple.dll.
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
{
Assembly newAssembly = null;
// Get the DLL name from the Name argument.
string[] nameParts = args.Name.Split(',');
string dllName = nameParts[0];
try
{
string path = "";
if (condition)
{
path = "";
}
newAssembly = Assembly.LoadFile(path);
}
catch (Exception e)
{
throw (e);
}
return newAssembly;
}
用几行代码就可以完美解决了此问题.(PS.我喜欢完美哈,用在这里应该也很恰当:-) 心情愉快地说)