[英]How to use Castle.Windsor in an assembly loaded using reflection
假設我有一個庫Lib.dll,它使用Castle.Windsor初始化其服務。
我有一個主應用程序App.exe,該應用程序在運行時使用反射加載Lib.dll。 App.exe事先不知道Lib.dll的位置,僅在運行時才知道。
在這種情況下,當App.exe加載Lib.dll且Lib.dll初始化其服務時,將引發System.TypeInitializationException異常,因為Castle.Windsor無法找到服務類型。
Castle.MicroKernel.SubSystems.Conversion.ConverterException: Could not convert from 'Lib.TheServiceClass' to System.Type - Maybe type could not be found
at Castle.MicroKernel.SubSystems.Conversion.TypeNameConverter.PerformConversion(String value, Type targetType) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel\SubSystems\Conversion\TypeNameConverter.cs:line 91
at Castle.MicroKernel.SubSystems.Conversion.DefaultConversionManager.PerformConversion(String value, Type targetType) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel\SubSystems\Conversion\DefaultConversionManager.cs:line 134
at Castle.MicroKernel.SubSystems.Conversion.DefaultConversionManager.PerformConversion[TTarget](String value) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\MicroKernel\SubSystems\Conversion\DefaultConversionManager.cs:line 162
at Castle.Windsor.Installer.DefaultComponentInstaller.SetUpComponents(IConfiguration[] configurations, IWindsorContainer container, IConversionManager converter) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\Windsor\Installer\DefaultComponentInstaller.cs:line 196
at Castle.Windsor.Installer.DefaultComponentInstaller.SetUp(IWindsorContainer container, IConfigurationStore store) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\Windsor\Installer\DefaultComponentInstaller.cs:line 52
at Castle.Windsor.WindsorContainer.Install(IWindsorInstaller[] installers, DefaultComponentInstaller scope) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\Windsor\WindsorContainer.cs:line 327
at Castle.Windsor.WindsorContainer.Install(IWindsorInstaller[] installers) in e:\OSS.Code\Castle.Windsor\src\Castle.Windsor\Windsor\WindsorContainer.cs:line 674
顯然,Castle無法找到我的服務類,因為它位於App.exe目錄中的Lib.dll中。 當我將Lib.dll復制到App.exe目錄時,問題消失了,但是不必復制它是我們想要的。
那么,我在Lib.dll中的代碼如何告訴Castle.Windsor在正確的位置加載該類? (在Lib.dll位置而不是App.exe位置)
您可以嘗試通過AssemblyResolve事件在代碼中加載未解析的程序集
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
string typeToLoad = args.Name;
string myPath = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName;
return Assembly.LoadFile(...); //or return Assembly.GetExecutingAssembly() etc.
};
您可能會考慮將插件加載到具有不同私有路徑的單獨AppDomain中,請參閱AppDomainSetup 。 當然,有一個缺點是您需要為插件選擇一個單獨的應用程序域,但是有時這被認為是一種好習慣。
如果App.exe沒有為您提供Castle Windsor的容器實例來配置您的服務,則可能無法輕松,優雅地完成此操作。
如果它不是直接暴露的,也許您可以使用Service Locator訪問它? 還是使用對App.exe程序集的反射自行找到它?
最好的解決方案是App.exe中的代碼是否在您的庫中調用特定方法(即,它可以查找特定的接口實現,例如IModuleInitializer
或其他東西,創建它的實例,然后調用某種Initialize
方法,將容器實例傳遞給您的代碼)。
您還可以考慮像MEF這樣的可擴展性框架,但這可能有點過大,並且會對App.exe產生重大影響。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.