protected virtual void InitializeWindsor()
{
if (container == null)
{
container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
//register all services
container.Register(
AllTypes.FromAssembly(typeof (ProductService).Assembly)
.BasedOn<IService>()
.WithService.Select(type => FindService(type, typeof (IService))));
//register all repositories
container.Register(
AllTypes.FromAssembly(typeof (ProductRepository).Assembly)
.BasedOn<IRepository>()
.WithService.Select(type => FindService(type, typeof (IRepository))));
//and so on...
}
}
private static Type FindService(Type type, Type implements)
{
return FindService(type, implements, new Type[0]);
}
private static Type FindService(Type type, Type implements, ICollection<Type> typesToIgnore)
{
Type first = null;
Type[] interfaces = type.GetInterfaces();
foreach (Type theInterface in interfaces)
{
if (theInterface.GetInterface(implements.FullName) != null && !typesToIgnore.Contains(theInterface))
{
first = theInterface;
break;
}
}
return first;
}
The alternative is this. But this one doesn't handle future components and you have to register them one by one.
protected virtual void InitializeWindsor()
{
if (container == null)
{
container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
// Register all services
container.Register(
Component
.For<IProductService>()
.ImplementedBy<ProductService>());
container.Register(
Component
.For<IOrderService>()
.ImplementedBy<OrderService>());
// continue with all other services, repositories, etc..
}
}

4 comments:
The second one is not an option to the first one.
There's a lot of friction that can be resolved using an IoC Container (I intend to talk about that in my book hehehe).
The goal of having an IoC container in place is reaching that "it just works" nirvana when it comes to managing dependencies between components.
The first scenario that you showcased really does that, meaning if I add a new service and has some component depend on that service (via constructor or setter injections), it just works.
The second scenario on the other hand has the pain point of making me remember to register a service with the container every single time I create a new one. That gets even worse if you inject your controllers, since these tend to be created fairly often (every time some new functionality comes, usually you get a new controller).
Even so, I loved the post! Way to go Martin.
Bernardo Heynemann
Bernardo,
There is a need for both of them. I use the automatic registration for my controllers, presenters, services, repositories, etc but I register some components with "Component.For(..)" when I want a specific setup. For example, when I'm running my application in Sweden I want this payment provider and in UK I want another one but I don't want both and have to get them by component key.
Then you missed my point, hehehe.
I never said you shouldn't use Component.For. I just said that this approach introduces friction. If that's a tradeoff you are willing to do, by all means do it, but always favor the least-friction approach.
Cheers,
Bernardo Heyneman
Great! Then we have the same opinion then. Good to point out that both are needed thou for other readers. Thanks Bernardo.
Post a Comment