动态决定加载dll多个版本的完美方案

最近同事遇到一个问题,关于程序需要在动态的时候决定究竟要加载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);

None.gif  Assembly CurrentDomain_AssemblyResolve( object  sender, ResolveEventArgs args)
ExpandedBlockStart.gifContractedBlock.gif 
dot.gif {
InBlock.gif     Assembly newAssembly 
= null
InBlock.gif     
// Get the DLL name from the Name argument.
InBlock.gif
     string[] nameParts = args.Name.Split(',');
InBlock.gif     
string dllName = nameParts[0];
InBlock.gif     
try
ExpandedSubBlockStart.gifContractedSubBlock.gif     
dot.gif{
InBlock.gif         
string path = "";
InBlock.gif         
if (condition)
ExpandedSubBlockStart.gifContractedSubBlock.gif         
dot.gif{
InBlock.gif             path 
= "dot.gif";
ExpandedSubBlockEnd.gif         }

InBlock.gif         newAssembly 
= Assembly.LoadFile(path);
ExpandedSubBlockEnd.gif     }

InBlock.gif     
catch (Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif     
dot.gif{
InBlock.gif         
throw (e);
ExpandedSubBlockEnd.gif     }

InBlock.gif
InBlock.gif     
return newAssembly;
ExpandedBlockEnd.gif }

None.gif

 

用几行代码就可以完美解决了此问题.(PS.我喜欢完美哈,用在这里应该也很恰当:-) 心情愉快地说)

转载于:https://www.cnblogs.com/anders06/archive/2007/06/29/800472.html

你可能感兴趣的:(runtime)