[英]Get assembly reference without reflection or a known type
在當前框架的設計中,我仔細研究了所有類型的特定程序集,並根據找到的類型進行工作。 它搜索的程序集由應用程序引導程序/初始化程序確定。 程序集是在其中編譯的,因此可以通過以下類型強烈引用它們: typeof(SomeTypeInTheAssembly).Assembly
。 這很不錯,因為引導程序代碼對程序集中的類型有很強的引用,並且完全不用擔心完全限定名稱作為內聯字符串,如果程序集限定名稱發生更改,則需要手動保持其最新狀態。 但是我不喜歡在程序集中引用一些完全不相關的類型並依賴那里的類型。 (如果它移到另一個程序集該怎么辦?如果我們棄用/刪除該類型怎么辦?更改其名稱空間呢?)在代碼中,它看起來也有些怪異:
FrameworkAssemblyReader.Read(typeof(SomeAssemblyNamespace.SubNamespace.GraphingCalculator).Assembly);
現在,在我的引導程序代碼中,我對GraphingCalculator
有直接的依賴關系(盡管很瑣碎),這與引導程序階段無關(作為GraphingCalculator,它當然與獲取程序集引用無關)。 為了避免這種情況,在我打算以此方式使用的每個程序集中,我在其根目錄中添加了一個類:
namespace SomeAssemblyNamespace
{
public static class AssemblyReference
{
public static System.Reflection.Assembly Get
{
get
{
return typeof(AssemblyReference).Assembly;
}
}
}
}
這還不錯,因為然后我的引導代碼如下所示:
FrameworkAssemblyReader.Read(SomeAssembly.AssemblyReference.Get);
但是現在,我復制/粘貼了大約十二個帶有AssemblyReference
類的程序集,並且我只期望隨着在框架之上構建應用程序而使其繼續增長。 所以我的問題是,有沒有一種好的方法可以避免AssemblyReference
類的重復並且仍然以編程方式將程序集引用傳遞給基本框架,同時又可以避免在目標程序集中指向某些任意/無關類型的模糊性? 我的Google搜索似乎告訴我,沒有讓我強烈指向程序集的API或語言功能(例如用於類的typeof
),但是我希望這里的人提出了比避免類/解脫更好的解決方案。代碼重復。 還要注意,該代碼有時是針對Silverlight編譯的,因此我知道這可能會限制某些API /技術。 謝謝!
編輯:只是要添加另一個活動扳手,基於“浣熊”的答案,我應該提一下,我並不總是加載相同的程序集。 例如,我可能有一個適用於某些應用程序但不適用於某些應用程序的“ CarBuilding”程序集。 由引導程序決定是否要使用引導程序(以及開發人員正在使用的任何自定義命令)
EDITx2:要回答Jon Skeet的問題:客戶(或我們內部)將創建他們希望支持其應用程序的任何項目/ DLL。 反過來,這些項目將引用內部基本框架。 他們的項目可能包含資源(3D文件,圖像,文本,本地化等)和類似插件的類(它們實現腳本,我們在應用程序的生存期內根據需要發現並實例化/執行)。 此外,我們的系統提供了可選模塊(DLL),其中包含可重復使用的插件/內容,客戶端(或我們)在制作特定應用程序時可以利用這些插件/內容。 因此,您可能會看到類似以下的項目結構:
Solution
->MyAppBootstrapper_Android
->MyAppGUI_Android
->MyAppFramework
->MyAppResources
->MyAppAdditionalResources_Android
->MyAppBootstrapper_Silverlight
->MyAppGUI_Silverlight
->MyAppFramework
->MyAppResources
->MyAppAdditionalResources_Silverlight
->BaseFrameworkGraphingModule
引導程序項目連接依賴項,並提供應將哪些項目/ dll(程序集)提供給基本框架以進行發現。 請注意,在這種情況下,“ MyApp”在Android和Silverlight構建之間共享自己的微型框架並共享資源,但是兩者都有彼此獨立的引用。 Silverlight一個利用了BaseFrameworkGraphingModule
優勢,它們擁有特定於該平台的自己的資源。
因此,項目中的引導程序看起來像(盡管已簡化):
namespace MyAppBootstrapper_Android
{
public class Bootstrapper
{
public void Setup()
{
FrameworkAssemblyReader.Read(MyAppGUI_Android.AssemblyReference.Get);
FrameworkAssemblyReader.Read(MyAppFramework.AssemblyReference.Get);
FrameworkAssemblyReader.Read(MyAppResources.AssemblyReference.Get);
FrameworkAssemblyReader.Read(MyAppAdditionalResources_Android.AssemblyReference.Get);
}
}
}
namespace MyAppBootstrapper_Silverlight
{
public class Bootstrapper
{
public void Setup()
{
FrameworkAssemblyReader.Read(MyAppGUI_Silverlight.AssemblyReference.Get);
FrameworkAssemblyReader.Read(MyAppFramework.AssemblyReference.Get);
FrameworkAssemblyReader.Read(MyAppResources.AssemblyReference.Get);
FrameworkAssemblyReader.Read(MyAppAdditionalResources_Android.AssemblyReference.Get);
FrameworkAssemblyReader.Read(BaseFrameworkGraphingModule.AssemblyReference.Get);
}
}
}
因此,對於在基礎框架之上構建的每個應用程序,都會創建一個引導程序,該引導程序指示要包括的程序集(以及一些其他不相關的接線工作)。 為了具體回答該問題,該項目具有編譯時引用的每個所需程序集(這確保了所有DLL都打包在一起以進行Android / Silverlight部署,這是雙重職責,因為它們沒有動態下載到用戶的智能手機或Silverlight應用中)但打包在初始下載中。 關於引導程序如何知道要使用哪些程序集的問題,開發人員很清楚知道並放置了必要的FrameworkAssemblyReader.Read
調用。 我希望這有幫助! 感謝您抽出寶貴的時間來查看它。 我覺得自己一無是處(或者完全錯過了一個更好的解決方案/設計)。
最后,我忽略了(愚蠢地)提到我們也針對Android的Mono和不久的將來的WPF進行編譯。 WinRT可能會在將來添加,但是當我們談到它時,我將很高興過橋。 但是總的來說,由於各自以自己的方式用自己的平台特性編譯,我不可怕介意不同的平台有集引用拉動的方式不同而已。 如果平台之間有統一的語法,那會很好。
EDITx3:是的,另一個。 我提到過,但是沒有用一個示例來說明不是所有項目都需要或應該由基本框架閱讀。 例如,實用程序或業務邏輯項目的代碼與基本框架無關,但與客戶端應用程序相關。 因此,從上面的示例:
Solution
->MyAppBootstrapper_Android
->MyAppGUI_Android
->MyAppFramework
->MyAppResources
->MyAppAdditionalResources_Android
->MyCompanySharedUtilities
->MyAppBootstrapper_Silverlight
->MyAppGUI_Silverlight
->MyAppFramework
->MyAppResources
->MyAppAdditionalResources_Silverlight
->BaseFrameworkGraphingModule
->MyCompanySharedUtilities
MyAppGUI_Silverlight和MyAppFramework可以利用MyCompanySharedUtilities
,但開發人員可能無法通過FrameworkAssemblyReader.Read
運行它,因為它僅包含某些數學或業務規則的專有實現。
我不確定您希望客戶如何使用此代碼,因此此建議可能無關緊要,但是取消設置功能(至少從客戶端隱藏它)並使用它不是更有意義。某種配置文件?
<ReferencedAssemblies>
<ReferencedAssembly key="UnchangingKey" qualifiedName="SomeAssemblyName, version=1.0.0.0, Culture=neutral, PublicKeyToken=0123456789abcdef" />
</ReferencedAssemblies>
從配置文件加載程序集。 使用密鑰,如果完全限定的名稱發生更改,則不必更新應用程序,只需更新配置文件(並保持密鑰不變)即可。
基本上,這是Visual Studio用於其項目文件的方法。 這是我的一個VB項目的示例:
<ItemGroup>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="UIAutomationProvider">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="PresentationCore">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
編輯:
這是一個想法...如果您使用Reflection.Emit從XML配置文件生成程序集,該怎么辦? 您可以在生成的程序集中添加一個存根類,您的核心項目可以使用該存根類來創建對生成的程序集的硬引用,並且可以使用反射來探查每個引用程序集(在XML文件中)以創建對任何對象的硬引用。在引用的程序集中。 當引用的程序集之一發生更改時,您需要重新生成該程序集,但這不需要更改代碼。 您甚至可以將程序集生成代碼構建到核心項目中,以便用戶可以根據需要更新其項目。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.