2013-05-04 45 views
7

我需要添加和/或修改配置文件以允許更多的類和成員在PCL中共享(其中很多都是內置於框架中的,例如Thread.Sleep)。什麼是最好的方法來做到這一點?有什麼工具可以幫助嗎?



PS:我不是尋求anwser告訴我NO或停止。我想擁有可以在不同環境中共享的編譯一次的DLL。沒有平臺二進制文件,沒有重新編譯,沒有ifdef。


下面是我走到這一步:

自定義.NET可移植類庫配置文件?

要求:

  • 目標environements:5的Silverlight和.NET Framework 4.5。
  • 目的PCLS的:由RIA客戶端與ASP.NET服務器(不WCF)的共享基礎架構
  • 缺少默認配置文件什麼:XPath的,螺紋的方法,DynamicMethod的/的ILGenerator

PCL概況:參考大會\微軟\ Framework.NETPortable

  • 所有組件是存根,以 「重定目標」 屬性設置。
  • 所有組件具有標誌= 0x171:0×001被簽名,爲0x100是可重定向,並且量0x070在AssemblyNameFlags未定義(似乎沒有效果)
  • 組件之間的所有參考文獻都以「重定目標」屬性爲好。
  • 所有支持Silverlight的程序集版本均爲2.0.5.0。
  • 內置PCL二進制文件包含每個稱爲組件的兩個引用(例如:mscorlib程序2.0.5.0可重定向+ mscorlib程序4.0)

定製嘗試#1

  • 資料:Silverlight的5 +。 .NET框架4.5(輪廓24)
  • 複製SL5 mscorlib.dll中剖析24
  • 馬克SL5的mscorlib.dll爲重定目標(改變延遲簽名)
  • ReSharper的:沒能解決所有的擴展方法,誤差在泛型類型/值匹配
  • 生成:成功,運行:成功

定製嘗試#2

  • 簡介:Silverlight的5 + .NET Framework 4。5(輪廓24)
  • 全部複製SL5的DLL來分析24
  • 標記全部SL5的DLL爲重定目標(改變延遲簽名)
  • 標記爲可移植的
  • ReSharper的SL5的DLL之間的所有引用:未能解決所有的擴展方法,錯誤的泛型類型/值匹配
  • 生成:成功,運行:成功

定製嘗試#3

  • 資料:Silverlight的4 + .NET框架4.0.3(配置文件18)
  • 複印SL4 mscorlib.dll中到型材18
  • 馬克SL4 mscorlib.dll中作爲可重定目標(改變到延遲簽名)
  • ReSharper的:成功
  • 生成:成功,運行:成功

定製嘗試#4

  • 簡介:Silverlight的4 + .NET框架4.0.3(輪廓18)
  • 複製所有的DLL SL4來分析所有SL4的DLL到V4的18
  • 組.NET運行庫版本(原來的DLL有,效果未知)
  • 標記全部SL4的DLL爲重定目標(改變延遲簽名)
  • 標記爲可移植的
  • ReSharper的SL4的DLL之間的所有引用:成功
  • 生成:成功,運行:成功

定製嘗試#5繼承#4

  • 簡介:Silverlight的4 + .NET框架4.0.3(輪廓18)
  • 添加SL4的System.Numerics(包括在其他SL配置文件)到RedistList \ FrameworkList.xml
  • 將SL4的System.Xml.XPath(不包括在任何SL配​​置文件中)添加到RedistList \ FrameworkList.xml
  • 結果:無法解析System.Numerics和System.Xml.XPath from def行兇的PCL引用
  • 修正:參考兩個DLL文件手動 - 無法迫使他們是可移植的,儘管VS不會與非可重定向System.Numerics或System.Xml.XPath編譯由於以下
的注意問題

注:

  • 編譯錯誤:「......在未引用的程序規定,您必須添加一個引用組裝」。發生後,所有組件均採用可移植的,但它們之間的引用之一也不變爲「可移植的」

它可以在一定程度上,但相當麻煩的輕鬆定製現有引用DLL或添加新的,也不能用一個在覆蓋引用的DLL之後驗證PCL代碼(如果可能的話)。

+2

我知道你不是在尋找答案,告訴你只是停下來,但是你可以選擇你想要包含的框架的哪一部分,然後它就可以工作的想法是真的不是一個明智的。即使你發現某種程度上的尷尬方法,遲早你會失去信心 - 在這一點上你會浪費很多時間。 – 2013-05-04 16:23:05

+0

但是,如果沒有適當的工具支持,它只會變得尷尬。如果有一個工具可以爲引用生成存根DLL,它會很好。 – AqD 2013-05-04 16:36:10

+0

假設您已經足夠了解支持這些API所需的其他內容......本機代碼和其他託管代碼的所有依賴關係。我認爲這不像你期待的那麼簡單。 – 2013-05-04 16:44:35

回答

4

NO。停。好吧,因爲這不是你想要聽到的,所以繼續你自己的風險。 :)這當然不被支持,IANAL,所以我不知道它是否會被許可協議所允許。

這聽起來像你現有的解決方案的主要問題是,你不能選擇單獨的API添加到便攜式配置文件。要做到這一點,你可以在現有的引用程序集上使用ildasm,然後添加你想要的API(可能通過從另一個引用程序集上運行ildasm的結果複製它們),然後使用ilasm創建你自己的引用版本具有這些附加API的程序集。

您需要延遲簽名和/或禁用用這種方式修改的程序集密鑰的強名稱密鑰驗證。

另一種選擇是使用類型轉發,如我的回答here中所述。在這種情況下,您最終會將主代碼視爲可共享,並依賴於每個平臺都不相同的DLL。

+0

類型轉發似乎是一個好主意。因此,理論上應該可以將所有API的相交部分進行包裝,然後將它們轉發到正確的程序集。但必須有一個工具來自動化.. – AqD 2013-05-11 17:51:28

10

既然你不會採取NOSTOP作爲一個答案讓我嘗試解釋爲什麼這是一個壞主意。簡短的回答是:如果PCL不暴露API,通常是因爲它不起作用。

首先,PCL沒有它自己的一套API。 PCL只是暴露了你想要定位的一組給定平臺之間的API交集。現在,有些情況下,API級別的交叉點會產生比PCL公開的API更多的API。有幾個重複的原因可能是這種情況。

  1. 這個API是不是用於所有平臺
  2. 這個API可用但不實際工作
  3. API的使用不同的組件定義

第一種應該是顯而易見的。 PCL本身並不是一個真正的平臺,只是揭示了那裏的一切。所以我們不能給你所有平臺上實際不存在的API。畢竟,我們揭露了路口。

第二個聽起來有點奇怪,但實際上確實發生。舉個例子來說,在Windows Phone 7的文件IO Althought的File class在技術上是可以在Windows Phone上,它的記錄作爲

This type is present to support the .NET Compact Framework infrastructure in Silverlight for Windows Phone, and it is not intended to be used in your application code.

你可能會說「我該怎麼照顧?」只需嘗試一下,但您會發現手機上的安全模式會阻止您訪問您正在查找的文件。因此,在PCL中公開這個API不會有幫助。事實上,我們的團隊認爲這實際上會傷害你,因爲它會導致你失去一條不可移動的路徑。

關於在不同程序集中實現的API的第三個問題涉及更多一點。爲了理解爲什麼這是一個問題,您需要考慮CLR如何處理一般的API。例如,CLR沒有像加載Java一樣加載單個類型的概念。在.NET中,類型是在程序集中實現的,爲了使用它們(「加載它們」),需要加載定義類型的程序集。在封面下,類型引用包括命名空間限定類型名稱以及類型定義在其中的程序集。通常,具有相同名稱空間限定名稱但位於不同程序集中的類型被認爲是不同的。例如,類型MyNamespace.MyType, Assembly1MyNamespace.MyType, Assembly2。請注意,程序集本身也有一個完全合格的名稱的概念;它包含程序集名稱和公鑰標記。這允許兩家公司生產一個名爲「Foo」的程序集並且不會混淆CLR(當然,假設它們使用不同的密鑰簽名)。所以實質上,加載類型需要幾個步驟:找到定義類型的程序集,加載該程序集,然後加載類型。

Usally,不同的.NET平臺使用不同的密鑰對平臺組件,例如,mscorlib程序。現在您可能想知道如何在.NET Framework上使用Silverlight中的類型。其原因是CLR具有裝配整理的概念。裝配不解決方案允許.NET Framework將對Silverlight的mscorlib的引用視爲對桌面版本的引用。這是有效的,因爲Silverlight的mscorlib被設計爲.NET Framework版本的一個子集(針對特定版本的組合)。

儘管這聽起來像靈丹妙藥彌合一切分歧paltform,它實際上不是。隨着時間的推移,不同的平臺選擇不同的裝配係數以ICommand爲例。它在.NET 4和Silverlight 4中可用。但是,在WPF中,它在PresentationCore.dll中實現,而Silverlight將它放在System.Windows.dll中。爲了理解爲什麼PCL在面向.NET 4和Silverlight 4時不暴露ICommand,讓我們看看如果PCL公開它會發生什麼。

在PCL,我們必須把ICommnad在一些組裝。我們可以選擇使用Silverlight程序集或完整的框架。無論我們會選哪一個,類型不會在其他平臺上的解決作爲PresenationCore.dll僅在.NET 4中存在,只有System.Windows.dll中在Silverlight 4

存在我們允許引用解決了這個問題用於System.Windows.dll中的ICommand以在完整框架上成功。我們是如何做到這一點的?答案是類型轉發。類型轉發允許程序集說「我定義了一個Foo類型」。當CLR嘗試從該程序集加載Foo類型時,程序集實際上會說「不,不 - Foo類型實際上是在其他程序集欄中定義的」。換句話說,程序集Foo包含類似於Bar的版本類型的指針。我們稱這些指針爲轉發條目。

這個概念使我們能夠通過將System.Windows.dll添加到包含實際實現類型的完整框架來解決ICommand不匹配問題。 PCL現在可以在System.Windows.dll中爲您提供ICommand,並且可以確保類型加載請求可以在.NET Framework和Silverlight上都成功。但是,這要求至少定位.NET Framework 4.5,因爲以前的版本沒有類型轉發。

對於予以曝光,但不是我們與平臺擁有者共同努力,縮小差距的所有API。我們有,基本上兩種策略:

  1. 我們要求平臺所有者添加缺少的API或鍵入轉發
  2. 我們的船在出帶外的時尚便攜式實施方案。以AsyncHttpClient爲例。

但是,「只是」將它添加到PCL不起作用。

編輯:如果您錯過了PCL中的功能,您可以隨時解除阻止。我們的測試員丹尼爾有written a blog post,它顯示了一些你可以使用的技術。

+0

謝謝。但是,除非微軟將我想要的東西添加到PCL中,否則沒有其他選擇。作爲解決方案,我不能採取非解決方案。 – AqD 2013-05-11 17:46:19

+0

您可以解決此問題,而無需調整PCL參考程序集。我們的測試人員撰寫了一篇關於可能的解決方案的優秀博客我已將它添加到答案中。 – 2013-05-14 04:05:44