日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

【转】C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁

發(fā)布時間:2023/12/10 C# 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)自:https://www.cnblogs.com/marvin/p/PutDllToSpecificFolder.html?utm_source=tuicool&utm_medium=referral

?

系列文章

  • C#開發(fā)奇技淫巧一:調(diào)試windows系統(tǒng)服務(wù)
  • C#開發(fā)奇技淫巧二:根據(jù)dll文件加載C++或者Delphi插件
  • C#開發(fā)奇技淫巧三:把dll放在不同的目錄讓你的程序更整潔

程序目錄的整理

想必C#的開發(fā)者都遇到過這個問題,引用的dll都放在根目錄下,隨著項目的日益增大,根目錄下充滿了各種各樣的dll,非常的不美觀。

如果能夠把dll按照想要的目錄來存放,那么系統(tǒng)就美觀多了,以下是我常用的程序各文件的分布:

  • 【3rdLibs】
    • NLog.dll
    • Newtonsoft.Json.dll
    • ……
  • 【MyLibs】
  • 【Resources】
  • 【Images】
  • Excecutable.exe
  • Excecuteble.exe.config

網(wǎng)上有很多的文章述說這個,比如使用Assembly.Load,但是沒有說明在程序中怎么使用,也沒有給出具體的代碼。這里我結(jié)合自己多年的實踐經(jīng)驗,再把整個流程和方法詳細敘述一遍,以便各位看官有個具體的體會。

系統(tǒng)搜索dll的目錄以及順序

CLR解析一個程序集會在一個根目錄內(nèi)進行搜索,整個探索過程又稱Probing,這個根目錄很顯然就是當(dāng)前包含當(dāng)前程序集的目錄。

AppDomainSetup這個類存儲著探索目錄的信息,其成員包括:ApplicationBase、PrivateBinPath。

程序搜索dll的順序如下(區(qū)分強名稱簽名的和沒有強名稱簽名的程序集):

沒有做強名稱簽名的程序集:

  • 程序的根目錄
  • 根目錄下面,與被引用程序集同名的子目錄
  • 根目錄下面被明確定義為私有目錄的子目錄
  • 在目錄中查找的時候,如果dll查找不到,則會嘗試查找同名的exe
  • 如果程序集帶有區(qū)域性,而不是語言中立的,則還會嘗試查找以語言區(qū)域命名的子目錄

具有強名稱簽名的程序集:

  • 全局程序集緩存
  • 如果有定義codebase,則以codebase定義為準,如果codebase指定的路徑找不到,則直接報告錯誤
  • 程序的根目錄
  • 根目錄下面,與被引用程序集同名的子目錄
  • 根目錄下面被明確定義為私有目錄的子目錄
  • 在目錄中查找的時候,如果dll查找不到,則會嘗試查找同名的exe
  • 如果程序集帶有區(qū)域性,而不是語言中立的,則還會嘗試查找以語言區(qū)域命名的子目錄

如何讓程序識別不同目錄下的dll?

我們看到,上面的順序無論是否有強名稱簽名看,都提到了一個名詞“私有目錄”

方法一:配置App.config文件的privatePath——【推薦】

這是最簡單的方法,當(dāng)然也有一定的局限性,就是沒法對dll做控制,另外,無法解決第三方DllImprt中引入的程序集不在根目錄下的問題,不過無論怎么說,這個都基本解決了問題。

配置如下,多個目錄用;分隔

<runtime><assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"><probing privatePath="3rdLib;MyLibs;SubFolder\Sub.dll"/></assemblyBinding> </runtime>

方法二:訂閱程序集解析事件AssemblyResolve在代碼中解析

應(yīng)用程序集域中支持在程序集解析時的處理:AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;。通過這個事件,我們可以在程序集解析時,根據(jù)不同的程序集做不用的處理,比如加載x86的程序集還是64位的程序集,當(dāng)然也就可以指定程序集目錄了

這也正是Assembly.Load和Assembly.LoadFrom等方法的用武之地。

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {AssemblyName assemblyName = new AssemblyName(args.Name);return Assembly.LoadFrom(Path.Combine(baseDirectory, "3rdLibs")); }

方法三:在加載使用到dll的代碼之前設(shè)置重置當(dāng)前環(huán)境的目錄

這個方法就是通過Environment.CurrentDirectory=customPath,這樣,在調(diào)用dll方法時,因為目錄已經(jīng)切換到了
這是一個取巧的方法,不是很實用,要來回切換程序集目錄,但是在某些情況下非常好用

如何處理[dllImport]中的程序集的加載

自己寫dllImport

如果是自己寫,那么久好控制了,可以直接指定相對的目錄DllImport(3rdLibs\NLog.dll)。不過這種方法不一定可靠,在某些系統(tǒng)硬是加載不了,如果使用了dllImport還是,推薦下面的另外一種方法。

引用的C#的插件又使用了dllImport

這是很多文章都沒有提及的:

因為無法更改路徑,那么只能夠使用上述特殊的方法,更改當(dāng)前程序的路徑

當(dāng)然,還有更省事一點的做法,就是在系統(tǒng)環(huán)境中,增加一條記錄,指向要加載的dll的所在目錄。因為C++的代碼中,Windows目錄和Windows\System32目錄以及環(huán)境變量設(shè)定的目錄都是搜索路徑之一。

這里提供怎么從C#中修改系統(tǒng)環(huán)境變量的代碼:

static void AddEnvironmentPaths(IEnumerable<string> paths) {var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty }; string newPath = string.Join(Path.PathSeparator.ToString(), path.Concat(paths)); Environment.SetEnvironmentVariable("PATH", newPath); }

參考文章

  • 淺談.NET中程序集的動態(tài)加載
  • 再談CLR查找和加載程序集的方式,查找程序集
  • 深入理解CLR類加載機制
  • C#程序集加載方法

?

?

如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續(xù)關(guān)注我的文章,請掃描二維碼,關(guān)注馬非碼的微信公眾號,我會將我的文章推送給您,并和您一起分享我日常閱讀過的優(yōu)質(zhì)文章。本文版權(quán)歸作者和博客園共有,來源網(wǎng)址:http://www.cnblogs.com/marvin/歡迎各位轉(zhuǎn)載,但是未經(jīng)作者本人同意,轉(zhuǎn)載文章之后必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責(zé) 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的【转】C#开发奇技淫巧三:把dll放在不同的目录让你的程序更整洁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。