问题
If I have defined in config:
container.Register(
Component.For<X.Y.Z.IActivityService>()
.ImplementedBy<X.Y.Z.ActivityService>()
.ServiceOverrides(ServiceOverride.ForKey("Listeners").Eq(new [] { typeof(X.Y.Z.DefaultActivityListener).FullName }))
.LifeStyle.Transient
);
and I wish to extend this configuration and add a new item to the Listeners array property such that the final configuration is effectively:
container.Register(
Component.For<X.Y.Z.IActivityService>()
.ImplementedBy<X.Y.Z.ActivityService>()
.ServiceOverrides(ServiceOverride.ForKey("Listeners").Eq(new [] { typeof(X.Y.Z.DefaultActivityListener).FullName, "MyOtherListenerID" }))
.LifeStyle.Transient
);
must I know the contents of the "array" when first registering the component, or can I retrieve the component registration and add to it?
I wish to implement my config using the decorator pattern such that I can build my container, and then extend it as needed for different scenarios. This means I need to be able to access the already configured components and add to them.
Was thinking of having a class DefaultConfig
which return the default setup and then one of more "DecoratedConfig
" classes, that would extend the default config.
So I would have
IWindsorContaner c = new DecoratedConfig(new DefaultConfig()).InitialiseContainer();
DefaultConfig
would set up the ActivityService
with a DefaultActivityListener
(as shown in example).
DecoratedConfig
would recognise that ActivityService
had been created and add its own Listener implementation to the Listeners
array on ActivityService
.
Thanks.
回答1:
Subscribe to the Kernel.ComponentModelCreated
event. You can change any component parameter from there. See this. It doesn't have to be a facility who does this, but it's convenient.
回答2:
@mausch, adusting the ComponentModel
configuration appears to be the solution.
The below test effecitvely does what I require without having to hook in to the ComponentModelCreatedEvent
so I can make the changes even after the component model is created.
I will wrap the functionality as an extension method, and try and fit to a fluent API.
[TestMethod]
public void ArrayPropertyTestApi3()
{
using (Castle.Windsor.WindsorContainer container = new Castle.Windsor.WindsorContainer())
{
container.Register(Component.For<Components.A>().ServiceOverrides(ServiceOverride.ForKey("I").Eq(new[] { typeof(Components.B).FullName })));
container.Register(Component.For<Components.B>());
container.Register(Component.For<Components.C>());
IHandler h = container.Kernel.GetHandler(typeof(Components.A));
if (h != null)
{
var config = h.ComponentModel.Configuration;
if (config != null)
{
var items = config.Children.Single(c => c.Name == "parameters")
.Children.Single(c => c.Name == "I")
.Children.Single(c => c.Name == "list")
as MutableConfiguration;
items.Children.Add(new MutableConfiguration("item", string.Format("${{{0}}}", typeof(Components.C).FullName)));
}
}
Components.A svc = container.Resolve<Components.A>();
Assert.IsTrue(svc.I.Length == 2);
Assert.IsTrue(svc.I[0].Name == "B");
Assert.IsTrue(svc.I[1].Name == "C");
}
}
回答3:
It is preferable to use the ComponentModel construction contributors with the IContributeComponentModelConstruction
interface since it is the recommended way of configuring your components further.
To do so, you would implement the interface to specify the changes to apply to configuration
public class ChangeConfiguration : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
// filter your model to match the subset you're interested in
// change the configuration for matching models
}
}
Then before registering your components, you just add the class to your container:
container.Kernel.ComponentModelBuilder.AddContributor(new ChangeConfiguration());
All components will then pass through this class, where you can change their configuration. In your case changeing the listener list, etc (I guess this is the previous name of the interceptors)
来源:https://stackoverflow.com/questions/938898/castle-windsor-how-can-i-update-a-components-registration