2011-09-26 30 views
23

從版本3.0開始,.NET會在C:\ Program Files \ Reference Assemblies \ Microsoft ....下安裝一堆不同的「參考程序集」,以支持不同的配置文件(如.NET 3.5客戶端配置文件,Silverlight配置文件)。其中每一個都是一個正確的.NET程序集,其中只包含元數據 - 無IL代碼 - 並且每個程序集都標有ReferenceAssemblyAttribute。元數據僅限於適用配置文件中提供的類型和成員 - 這就是智能感知如何顯示一組受限制的類型和成員。運行時不使用引用程序集。如何創建和使用.NET僅用於元數據的「引用程序集」?

我從this blog post瞭解了一點。

我想爲我的庫創建和使用這樣的引用程序集。

  1. 如何創建一個只有元數據的程序集 - 是否有一些編譯器標誌或ildasm後處理器?
  2. 是否有屬性可以控制哪些類型導出到不同'配置文件'?
  3. 如何在運行時引用程序集解析 - 如果我的應用程序目錄中存在引用程序集而不是「真實」程序集,而不是GAC中,將繼續探測,並且我的AssemblyResolve事件觸發,以便我可以在運行時提供實際裝配?

任何想法或指向哪裏我可以瞭解更多關於這將不勝感激。

更新:環顧一下,我看到.NET 3.0'引用程序集'似乎有一些代碼,並且Reference Assembly attribute僅在.NET 4.0中添加。因此,新的運行時可能會改變一些行爲。

爲什麼?對於我的Excel-DNA(http://exceldna.codeplex.com)加載項庫,我通過將引用的程序集作爲資源打包到.xll文件中來創建單個文件.xll加載項。打包的程序集包括用戶的插件代碼以及Excel-DNA管理的庫(可能由用戶的程序集引用)。

聽起來相當複雜,但大部分時間都工作得非常好 - 外接程序是一個小文件,所以沒有安裝分發問題。由於版本不同,我遇到了(並非意外的)問題 - 如果將舊版本的Excel-DNA託管庫作爲文件運行,運行時將加載該文件而不是打包的文件(我從來沒有機會干涉加載)。

我希望爲我的Excel-DNA管理部分製作一個參考彙編,用戶在編譯其加載項時可以指向它。但是如果他們在運行時錯誤地使用了這個程序集版本,那麼運行時將無法加載它,並且讓我有機會從資源加載真正的程序集。

+1

你爲什麼要這麼做? – svick

回答

9

要建立一個參照裝配,你將這個行添加到您AssemblyInfo.cs文件:

[assembly: ReferenceAssembly] 

要加載他人,你可以在運行時引用它們像往常一樣從你的VisualStudio項目引用,或動態:

Assembly.ReflectionOnlyLoad()

Assembly.ReflectionOnlyLoadFrom()


如果添加使用VisualStudio中裝配到元/參考基準,則智能感知和建設項目將工作得很好,但是如果你試圖對一個執行應用程序,你會得到一個錯誤:

System.BadImageFormatException: Cannot load a reference assembly for execution.

所以期望的是,在運行時,您將替換具有相同元數據簽名的實際程序集。

如果您已經使用Assembly.ReflectionOnlyLoad()動態加載程序集,那麼您只能對它進行所有反射操作(讀取類型,方法,屬性,屬性等,但不能動態調用它們中的任何一個)。


我很好奇你的用例是用於創建一個僅用於元數據的程序集。我從來沒有這樣做過,並希望知道你是否發現了一些有趣的用途...

+2

構成了一個**人造的例子**:您可以使用例如.NET Framework創建一個.NET程序集的本地圖像。單聲道mkbundle.exe。現在,您仍然可以允許插件dll訪問原始程序集的公共接口。我相信你可以通過這種方式來實現。如果有的話會導致_really_ obfuscated和_large_程序集:) – sehe

+0

添加ReferenceAssembly屬性不會將輸出更改爲像.NET 4引用程序集這樣的僅用於元數據的程序集。我試圖找出如何建立這些。我將不得不嘗試,但在處理完BadImageFormatException後,你認爲程序集解析會調用我的AssemblyResolve處理程序嗎? (我會在問題中添加用例的詳細信息。) – Govert

+0

我已經添加了一些關於我感興趣的信息。 @sehe離商標不遠了!那些打包的程序集實際上很小,因爲我在打包之前對它們進行了壓縮,並且CLI程序集壓縮得非常好。結果只會在'obscurity'意義上被模糊處理 - .NET程序集不在您的面前,所以您必須在將它們指向ILSpy之前做一些工作。但是這種混淆器會是另一個很好的用例。 – Govert

2

是的,這是.NET 4.0的新功能。我相當確信這是爲了避免.NET 2.0 Service Pack中令人討厭的版本問題。最好的例子是WaitHandle.WaitOne(int)重載,在SP2中添加並記錄。一個流行的重載,因爲它避免了在WaitOne(int,bool)過載中猜測* exitContext的正確值。問題是,當程序運行在比SP2更早的2.0版本時,程序被炸了。診斷無論是。隔離參考組件確保這不能再發生了。

認爲這些參考組件被從編譯的程序集的副本開始(就像是在以前的版本中完成)並運行他們創造通過一個從組件中剝離IL的工具,然而這個工具並不適用於我們,bin/netfx 4.0工具中沒有任何可以做到這一點的Windows 7.1 SDK子目錄,這不是一個經常使用的工具,所以它可能不是生產質量:)

+0

啊!我認爲這就是我正在尋找的工具... – Govert

+1

漢斯,我相信這個工具實際上比你想象的更經常使用。只有元數據的程序集也用於引導Core .Net Framework程序集,如[這個答案](http://stackoverflow.com/questions/1316518/z/1316587)中解釋的一個關於如何編譯.Net的問題框架程序集。當然,還有通過特殊工具對這些程序集進行的其他更改,例如引用「m_value」成員的原始類型替換爲對this的引用。 –

+0

感謝凱文指向另一個問題。所以這些引用程序集是「脫水」的僅包含元數據的程序集。 – Govert

1

您可能對塞西爾圖書館(來自Mono)有好運;我認爲實現允許ILMerge功能,它可能也只寫元數據的程序集。

我已經掃描代碼庫(文檔是稀疏的),但沒有發現任何明顯的線索尚未...

YYMV

3

如果你仍然有興趣在這個可能性,我做了一個基於Mono.Cecil的il-repack項目的分支,它接受「/ meta」命令行參數以生成僅用於公共和受保護類型的僅用於元數據的程序集。

https://github.com/KarimLUCCIN/il-repack/tree/xna

(我試了一下就滿XNA框架及其AFAIK工作...)

+0

謝謝(也可以在此回覆)!仍然感興趣 - 當我有機會時我會看看。 – Govert

相關問題