I am new to IoC and Castle Windsor.
The question is more related to IoC, but i just chose Castle as my weapon of choice.
I immediately ran into a problem that it seems impossible to construct the container from a config file or from a singleton.
The only way seeming to work for me is to use a Builder function that will construct the whole container each time and then let me specify the types, look at this example:
I have a view:
public interface IView
{
}
There are 2 concrete implementations of this view:
public class ConcreteViewA : IView
{
}
public class ConcreteViewB : IView
{
}
I have a controller that operates on the view:
public class Controller
{
public Controller(IView view) { }
public void Load() { }
}
I create a function that constructs my IoC container and register the common types, the only type i can register is my controller, as this is all that stays the same:
WindsorContainer BuildContainer()
{
var container = new WindsorContainer();
container.Register(Component.For<Controller>().ImplementedBy<Controller>());
return container;
}
I have 2 (Root) entry points:
void RootMethod1()
{
var container = BuildContainer();
container.Register(Component.For<IView>().ImplementedBy<ConcreteViewA>());
var controller = container.Resolve<Controller>();
controller.Load();
}
void RootMethod2()
{
var container = BuildContainer();
container.Register(Component.For<IView>().ImplementedBy<ConcreteViewB>());
var controller = container.Resolve<Controller>();
controller.Load();
}
As you can see I have to rebuild the container each time as i need to tell it what to use for IView for each of the context i am in. What if the Container is expensive to rebuild (Lots of types etc), how can I design this?
From what I understand, you need two different instances of the Controller class (each one constructed with a different IView type). The easiest way to achieve this is to register two components with different names and different dependencies.
WindsorContainer BuildContainer()
{
var container = new WindsorContainer();
container.Register(Component.For<Controller>().Named("ControllerWithViewA")
.ImplementedBy<Controller>()
.DependsOn(Property.ForKey(typeof(IView))
.Is(typeof(ConcreteViewA)));
container.Register(Component.For<Controller>().Named("ControllerWithViewB")
.ImplementedBy<Controller>()
.DependsOn(Property.ForKey(typeof(IView))
.Is(typeof(ConcreteViewB)));
return container;
}
You can then ask for any controller as and when required.
void RootMethod1()
{
var container = BuildContainer();
var controller = container.Resolve<Controller>("ControllerWithViewA");
controller.Load();
}
void RootMethod2()
{
var controller = container.Resolve<Controller>("ControllerWithViewB");
controller.Load();
}
A few more things to keep in mind when using DI
Build your container only once (Building it again and again is a waste of time and resources).
Be very sure which dependencies to inject and which not to. Overusing DI for everything can result in a bloated container which is a maintenance nightmare.
Be informed about the life cycle of your components (Singleton, Transient, per thread etc). Especially with Castle the default lifestyle is singleton which might create inconsistent behavior in a multi-threaded scenario.
You could look at using a handler selector. This would allow you to dynamically choose which view to resolve based on whatever code you choose. See here .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.