Castle Windsor:如何通过xml配置覆盖组件注册

时间:2022-10-19 00:09:36

I'm trying to overwrite a component registration (done via xml) with another one (in another xml, loaded via code using container.Install(Configuration.FromXmlFile("...")) that has the same component id, but i receive an error saying:

我正在尝试用另一个(在另一个xml中,通过使用container.Install(Configuration.FromXmlFile(“...”)的代码加载)来覆盖组件注册(通过xml完成​​),它具有相同的组件ID,但是我收到错误说:

"Component COMP_ID could not be registered. There is already a component with that name. Did you want to modify the existing component instead? If not, make sure you specify a unique name."

“组件COMP_ID无法注册。已经有一个具有该名称的组件。您是否要修改现有组件?如果没有,请确保指定唯一名称。”

The thing is, i in fact actually would like to modify the existing component, to be able to define basic wiring in a basic castle.xml file and then overwrite it, in another custom.xml file, loaded after the basic one.

事实上,我实际上想要修改现有组件,以便能够在基本的castle.xml文件中定义基本连线,然后在另一个custom.xml文件中覆盖它,在基本的文件之后加载。

I'm trying to use the same component id because a tought it would have rewritten the previous registration.

我正在尝试使用相同的组件ID,因为它应该重写之前的注册。

The reality is that i would like to change wich implementation is used to respond to a service, the component id is just a try that i've done. Since Castle has a policy of first-registration-wins, it would be enough for example to switch to a last-registration-wins, for example.

实际情况是,我想改变用于响应服务的实现,组件ID只是我已经完成的尝试。由于Castle具有首次注册获胜的策略,例如,切换到最后注册获胜就足够了。

Concrete example

Let's use the example of an ILogger interface.

我们来看一个ILogger接口的例子。

The basic castle.xml (loaded always) would be like this:

基本的castle.xml(总是加载)将是这样的:

<component id="logger" service="ILogger" type="NullLogger" ></component>

The castle.dev.xml file (loaded only in the dev ambient, after the default one) would look like this:

castle.dev.xml文件(仅在dev环境中加载,默认加载后)将如下所示:

<component id="logger" service="ILogger" type="AspNetTraceLogger" ></component>

The castle.prod.xml file (loaded only in production ambient, after the default one, instead of the dev one) would look like this:

castle.prod.xml文件(仅在生产环境中加载,在默认加载后,而不是开发者)将如下所示:

<component id="logger" service="ILogger" type="SqlServerLogger" ></component>

Now: for each of these configurations, I would like to say "respond to ILogger requests with this impl", so I need to have only one of them to respond to requests for ILogger at each time.

现在:对于这些配置中的每一个,我想说“用这个impl响应ILogger请求”,所以我只需要其中一个响应每次ILogger的请求。

Anyone have any idea?

有人有什么想法吗?

update

I'll add: as of now i'm using a, shall we say, "reverse overwriting" technique, where i load the overwriting files "first", before the corresponding "default" ones. In this way, since the policy is first-wins, i can declare them as overwrites, even though internally they are declared before. The problem with this approach is when i have an interface that i know will be implemented more than once (say, IWhateverListener): in this case i cannot remove the other ones already registered, and cannot use the first-wins solution because later on i'll use a ResolveAll() and the "default ones" will be used too.

我将补充:截至目前我正在使用a,我们应该说,“反向覆盖”技术,我在相应的“默认”之前加载覆盖文件“first”。通过这种方式,由于策略是第一次获胜,我可以将它们声明为覆盖,即使它们之前已在内部声明。这种方法的问题是当我有一个我知道将不止一次实现的接口(比如,IWhateverListener):在这种情况下我不能删除已注册的其他接口,并且不能使用先赢的解决方案因为稍后我将使用ResolveAll(),并且也将使用“默认值”。

1 个解决方案

#1


1  

Don't try to register several components with the same ID, or try to hack around it.

不要尝试使用相同的ID注册多个组件,或尝试破解它。

If you must use XML, take a look at defines and ifs.

如果必须使用XML,请查看定义和ifs。

Otherwise just use different installers, one for each environment, and at application startup register the one you want

否则只需使用不同的安装程序,每个环境一个,并在应用程序启动时注册您想要的安装程序

#1


1  

Don't try to register several components with the same ID, or try to hack around it.

不要尝试使用相同的ID注册多个组件,或尝试破解它。

If you must use XML, take a look at defines and ifs.

如果必须使用XML,请查看定义和ifs。

Otherwise just use different installers, one for each environment, and at application startup register the one you want

否则只需使用不同的安装程序,每个环境一个,并在应用程序启动时注册您想要的安装程序