C# 如何在使用反射加载的程序集中使用Castle.Windsor

C# 如何在使用反射加载的程序集中使用Castle.Windsor,c#,.net,reflection,castle-windsor,appdomain,C#,.net,Reflection,Castle Windsor,Appdomain,假设我有一个Lib.dll库,它使用Castle.Windsor初始化它的服务 我有一个主应用程序App.exe,它使用反射在运行时加载Lib.dll。App.exe事先不知道Lib.dll的位置,只在运行时知道 在这种情况下,当App.exe加载Lib.dll并初始化其服务时,会引发System.TypeInitializationException异常,因为Castle.Windsor找不到服务类型 Castle.MicroKernel.SubSystems.Conversion.Conve

假设我有一个Lib.dll库,它使用Castle.Windsor初始化它的服务

我有一个主应用程序App.exe,它使用反射在运行时加载Lib.dll。App.exe事先不知道Lib.dll的位置,只在运行时知道

在这种情况下,当App.exe加载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显然找不到我的服务类,因为它位于Lib.dll中,而Lib.dll不在App.exe目录中。当我将Lib.dll复制到App.exe目录时,问题就消失了,但我们不想复制它


那么,我在Lib.dll中的代码如何告诉Castle.Windsor将类加载到正确的位置呢?(在LIB DLL位置而不是App.EXE位置)

,您可能会考虑将插件加载到单独的AppDe域中,使用不同的私有路径,查看。当然,你的插件有一个单独的应用程序域的缺点,但是有时这被认为是一个很好的实践。

你可能会考虑将插件加载到一个单独的AppDeavy中,用不同的私有路径来查看。当然,有一个缺点是你需要为你的插件提供一个单独的应用程序域,但有时这被认为是一个好的做法。

如果app.exe不为你提供Castle Windsor的容器实例来配置你的服务,你可能无法轻松优雅地完成这项工作

如果它不是直接暴露的,也许你可以使用?或者使用App.exe程序集上的反射自行查找它

最好的解决方案是App.exe中的代码调用库中的特定方法(即,它可以查找特定的接口实现,如
IModuleInitializer
或其他,创建它的实例,并调用某种
Initialize
方法将容器实例传递给代码)


您也可以考虑扩展性框架,例如,但这可能有点过分,并对App.exe产生很大影响。

如果App.exe不为您提供Castle Windsor的容器实例来配置您的服务,您可能无法轻松优雅地完成这项工作

如果它不是直接暴露的,也许你可以使用?或者使用App.exe程序集上的反射自行查找它

最好的解决方案是App.exe中的代码调用库中的特定方法(即,它可以查找特定的接口实现,如
IModuleInitializer
或其他,创建它的实例,并调用某种
Initialize
方法将容器实例传递给代码)


您也可以考虑扩展性框架,如,但这可能有点过分,对App.exe造成很大影响。

您可以尝试通过AssemblyResolve事件在代码中加载未解析的程序集


您可以尝试通过AssemblyResolve事件在代码中加载未解析的程序集


这容易吗?我可以将插件的路径添加到主应用程序的应用程序域吗?如果addtorpivatepath被声明为已过时:,并且只有当插件位于子目录中时它才能工作……有没有比在单独的应用程序域中加载更简单的方法?主要应用程序不在我的控制之下,我高度怀疑负责人是否愿意为了解决我的问题而做这些艰苦的工作。这容易吗?我可以将插件的路径添加到主应用程序的应用程序域吗?如果addtorpivatepath被声明为已过时:,并且只有当插件位于子目录中时它才能工作……有没有比在单独的应用程序域中加载更简单的方法?主应用程序不在我的控制之下,我高度怀疑负责人是否愿意为了解决我的问题而做这些艰苦的工作,你使用的是哪个版本。组件如何在容器中注册?@KrzysztofKoźmic 2.5.2您所说的组件如何注册是什么意思?我使用XML文件来定义服务扫描您共享XML文件并显示如何加载它?@KrzysztofKoźmic
new WindsorContainer().Install(Configuration.FromXmlFile(configFile))您也可以参考上面的堆栈跟踪OK,我们正在慢慢地到达那里。在哪里调用此代码?您使用的是哪个版本。组件如何在容器中注册?@KrzysztofKoźmic 2.5.2您所说的组件如何注册是什么意思?我使用XML文件来定义服务扫描您共享XML文件并显示如何加载它?@KrzysztofKoźmic
new WindsorContainer().Install(Configuration.FromXmlFile(configFile))您也可以参考上面的堆栈跟踪OK,我们正在慢慢地到达那里。在哪里调用此代码?
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.
};