我們的應用程序部署的時候,目錄結構一般不會只有運行程序的目錄這一個,我們可能在運行目錄下建子目錄,也可能使用System32目錄,也可能使用其它第三方的程序集。.Net程序集
首先會在GAC中搜索相應的版本,如果未找到則會應用程序配置文件中找(如果配置),最后到應用程序所在的路徑搜索。
如何可以將程序集部署的運行目錄的子目錄, 在app.config添加以下配置,其中probing的privatePath就是配置當前程序搜索的子目錄
<configuration>
... ... <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <probing privatePath="Plugins;Libs"/> </assemblyBinding> </runtime> </configuration>
當然我們也可以更詳細的配置,不過似乎一般這么用的很少,這里可以指定程序集名稱、公鑰、文化,版本重定向等等信息
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="myAssembly" publicKeyToken="32ab4ba45e0a69a1" culture="neutral" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/> <codeBase version="2.0.0.0" href="http://www.litwareinc.com/myAssembly.dll"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
Msdn地址:http://msdn.microsoft.com/zh-cn/library/twy1dw1e(v=vs.80).aspx
如何加載非運行目錄的程序集?也許有的人會想到反射,的確對應單獨的一個程序集我們可以直接調用使用 Assembly.LoadFile(@"XXX.dll");加載,再使用反射對其中的方法屬性進行調
用,但是如果這個程序集同時引用了其它的,非應用程序運行目錄下的程序集,這時就會出錯,這個問題該如何解決呢?
我曾嘗試用 Assembly.LoadFile(@"XXX.dll");加載那些依賴的程序集,但是沒有成功,調用繼續出錯。使用 AppDomain.CurrentDomain.GetAssemblies()查看,所有的應用程序集都已經加載到了當前應用程序域,但是為什么還是找不到依賴的哪些程序集呢?后來查詢未果,希望有高人能回答下。
最后使用了AppDomain.CurrentDomain.AssemblyResolve事件解決了以上問題,希望遇到同樣問題的同學們少走彎路,在程序初始化的時候添加監聽事件
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
在監聽的事件中遇到要加載額外的dll的時候,返回 Assembly.LoadFrom(strTempAssmbPath)即可
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { var strTempAssmbPath = ""; if ("qrcsharp" == args.Name.Substring(0, args.Name.IndexOf(","))) { var systemFolder = Environment.GetFolderPath(Environment.SpecialFolder.System); strTempAssmbPath = System.IO.Path.Combine(systemFolder, "qrcsharp.dll"); } return string.IsNullOrWhiteSpace(strTempAssmbPath) ? null : Assembly.LoadFrom(strTempAssmbPath); }