.Net代碼控制PrivateBinPath和ConfigurationFile的位置

來源:互聯網
上載者:User

標籤:.net   儲存   run   dom   var   ros   vat   module   contex   

.Net的WinForm程式有的時候讓人很煩的是,在執行目錄下總是一大堆的DLL,設定檔,最少則是個以下,多的時候怕有四五十個吧……,自己程式中的類庫,第三方的類庫……載入一起讓人感覺亂糟糟的,非常不爽。在下雖然在個人衛生上沒有什麼潔癖,可是對於應用程式的這個樣子確實沒有一點容忍力的,是可忍孰不可忍啊!

處理這些DLL還是比較簡單的,Configuration檔案裡就可以配置了。先將DLL分門別類,Core, Module, Misc等等,然後將這幾個目錄名稱加入App.config中。如:

<runtime>  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">    <probing privatePath="Castle;Core;Module;UI;Misc;"/>  </assemblyBinding></runtime>

嗯,現在看上去就舒服多了,各就各位的,清爽!慢……在主目錄下,出了我們的應用程式Exe可執行檔外,還有一個例外,app.config…… 多少還是有點兒不爽,怎麼辦呢?我們建個Data目錄,將config檔案移動進去吧~!說做就做,我們就把app.config移動到下級目錄了,開心啊,看看程式能運行不? 杯具發生了,程式運行毫無反應…… 用VS調試之,發現是找不到其他類庫中的類型導致的。也是,我們剛剛在config檔案中加了privatePath,現在有把這個檔案移動了,怎麼能載入到其他目錄下的DLL呢?

知道原因了,當然就好解決。據說configuration檔案的位置是可以指定的。AppDomainSetup.ConfiguraitonFile屬性就是指的這個。讓我們來試試…… 

分析一下:

要改config的路徑,當然是要在使用config之前咯,而且越早越好…… 哪裡比較早呢?嗯,Main函數,程式的入口是個不錯的選擇……

static class Program{     /// <summary>    /// 應用程式的主進入點。    /// </summary>    [STAThread]    static void Main()    {        AppDomain.CurrentDomain.SetupInformation.ConfigurationFile = "Data\MyApp.Config";         Application.Run(new MyAppForm());    }}

好,編譯,信心滿滿的再次運行程式,可是杯具再一次啊發生了,依然沒有反應……  

……在此調試,驚奇的發現這個屬性設定居然完全沒有效果,語句執行完後,該屬性值依然是預設值。於是查文檔啊,百度啊,Google啊~ 最後終於知道設定config的正確方法。

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", path);

嗯,這個這個……不是微軟在害人嗎…… 好了,停下抱怨繼續工作先…… 嗯,看到了,config檔案的位置生效了,指向了我們預定的位置,可是………… 杯具毫無意外的再次發生……DLL依然不能載入!

雖然我已經在AppDomainSetup裡看到了PrivateBinPath屬性,可是我卻一點興奮感覺都沒有,應該跟前面的結果類似把!

想想程式啟動並執行過程,PrivateBinPath是AppDomain.Current.SetupInformation裡的屬性,而這個屬性只有在AppDomain.Create的時候才會生效,在AppDomain已經建立後更改config的路徑再去設定這個值,應該是不行的。看來只好代碼裡來設定了。可是如何下手呢?

關門, 放Reflector!呵呵,讓我們看看AppDomain內部的情況。果其不然啊!SetupInforamtion只是其內部配置的一個Copy,這也就解釋了為什麼更改屬性卻沒有生效的原因!

public AppDomainSetup SetupInformation{    get    {        return new AppDomainSetup(this.FusionStore, true);    }}

看起來不動用終極手段是不行的了!反射!更改內部欄位來達到我們的目的!仔細檢查了以下代碼,發現AppDomain內部的Setup資訊是儲存在一個FunsionStore的Internal屬性裡的。好,我們就從這裡動手把!

AppDomain.CurrentDomain.SetData("PRIVATE_BINPATH", "Castle;Core;Module;UI;Misc;");AppDomain.CurrentDomain.SetData("BINPATH_PROBE_ONLY", "Castle;Core;Module;UI;Misc;");

這段代碼確實就更改了AppDomain.CurrentDomain.SetupInformation.PrivateBinPath的值了,可是運行發現類型還是不能載入!可能內部還有個什麼RefrefshConfiguraiton或UpdateCache之類的方法來重新整理!繼續找啊找的~ 終於發現了。是一個static extern的方法。呵呵……這下簡單了,看代碼!

在調試過程中,我們還發現Main方法不是最好的地方,所以我們將代碼放在了Program的靜態構造方法中,這裡是除了靜態欄位外的最早的起始地了。

static Program(){    AppDomain.CurrentDomain.SetData("PRIVATE_BINPATH", "Castle;Core;Module;UI;Misc;");    AppDomain.CurrentDomain.SetData("BINPATH_PROBE_ONLY", "Castle;Core;Module;UI;Misc;");    var m = typeof(AppDomainSetup).GetMethod("UpdateContextProperty", BindingFlags.NonPublic | BindingFlags.Static);    var funsion = typeof(AppDomain).GetMethod("GetFusionContext", BindingFlags.NonPublic | BindingFlags.Instance);    m.Invoke(null, new object[] { funsion.Invoke(AppDomain.CurrentDomain, null), "PRIVATE_BINPATH", "Castle;Core;Module;UI;Misc;" });}

嗯,迫不及待的編譯,運行!哇!毫不意外的,程式正常了,再看看應用程式目錄,只有一個乾乾淨淨的exe檔案的存在,真是爽到極點~ 

告訴你,exe檔案就一個,我可以!哈哈!

 最後提醒,如果Program裡有靜態欄位,不要定義為用其他類庫的類型,因為這個時候我們上述的方法還沒有執行到,會因為找不到類型而出錯的哦~

 

.Net代碼控制PrivateBinPath和ConfigurationFile的位置

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.