问题
With Castle Windsor, let's say I have the following classes:
public class LowLevelComponent
{
}
public class HighLevelComponent
{
readonly LowLevelComponent LowLevelComponent;
public HighLevelComponent(LowLevelComponent lowLevelComponent)
{
LowLevelComponent = lowLevelComponent;
}
}
public class ComponentBeingResolved
{
readonly LowLevelComponent LowLevelComponent;
readonly HighLevelComponent HighLevelComponent;
public ComponentBeingResolved(LowLevelComponent lowLevelComponent,
HighLevelComponent highLevelComponent)
{
LowLevelComponent = lowLevelComponent;
HighLevelComponent = highLevelComponent;
}
}
Registered in the easiest possible way:
container.Register(Component.For<LowLevelComponent>());
container.Register(Component.For<HighLevelComponent>());
container.Register(Component.For<ComponentBeingResolved>());
I'd like to get the same instance of LowLevelComponent
used in all dependencies each time I call Resolve.
So, after these calls:
var instance1 = container.Resolve<ComponentBeingResolved>();
var instance2 = container.Resolve<ComponentBeingResolved>();
The following assertions should be true:
instance1.LowLevelComponent == instance1.HighLevelComponent.LowLevelComponent
instance1.LowLevelComponent != instance2.LowLevelComponent
instance1.HighLevelComponent != instance2.HighLevelComponent
I'll also take "you're doing everything wrong, this is what you should do instead" as an answer :-)
回答1:
You must've heard people recommending to only call Resolve once for your app entry point (Main, Controller, etc.). Castle documentation has good guidelines on this.
回答2:
Based on Mauricio's link, I got it working using factories:
public interface IComponentFactory
{
T Get<T>();
}
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<LowLevelComponent>()
.LifeStyle.Custom<ContextualLifestyle>());
container.Register(Component.For<HighLevelComponent>()
.LifeStyle.Custom<ContextualLifestyle>());
container.Register(Component.For<IComponentFactory>().AsFactory());
//Register the "context-root" component in a child container
var subContainer = new WindsorContainer();
subContainer.Register(Component.For<ComponentBeingResolved>()
.LifeStyle.Transient);
container.AddChildContainer(subContainer);
container.Register(
Component.For<ComponentBeingResolved>()
.LifeStyle.Transient
//Here's the magic
.UsingFactoryMethod(
() =>
{
using (new ContainerContext(container))
return subContainer.Resolve<ComponentBeingResolved>();
}));
Usage:
var factory = container.Resolve<IComponentFactory>();
var instance1 = factory.Get<ComponentBeingResolved>();
var instance2 = factory.Get<ComponentBeingResolved>();
Not sure if this is a good hack or an ugly one, but it works wonderfully.
来源:https://stackoverflow.com/questions/5226659/castle-custom-lifestyle-per-resolve