In general, if you make an interface which only has one implementor, you're just writing things twice and wasting your time. Interfaces alone do not provide loose coupling if they're tightly coupled to one implementation... That said, if you want to mock these things in unit tests, that's usually a great sign that you'll inevitably need more than one implementor in real code.
I would consider it a bit of a code smell if nearly all your classes have interfaces though. That means they're almost all working with one another in one way or another. I would suspect that the classes are doing too much (since there's no helper classes) or you've abstracted too much (oh, I want a provider interface for gravity since that might change!).
I have experience with Ninject, not Castle Windsor, but the principles should be the same.
To understand dependency injection, it helps to recall how you wrote code without it. Typically, the DepartmentsController
constructor would look like something like this:
public DepartmentsController()
{
_repository = new DepartmentRepository();
}
The controller depends on the repository, and by placing it in the constructor we ensure that every DepartmentsController
is instantiated with a repository and begins its life in a valid state. By doing this, however, we make it more difficult to later swap one implementation of DepartmentRepository
for another. In particular, if we want to isolate the DepartmentsController
and test it independently, we're in trouble. How do we test this class without invoking actual calls to the database through DepartmentRepository
?
Your first example improves on this scenario by creating a "seam" between the objects: a point where the two are glued or stitched together that can be separated easily, especially for tests. Instead of creating the DepartmentRepository
itself, your controller can ask for it:
public object GetService(Type serviceType)
{
return _container.Kernel.HasComponent(serviceType) ? _container.Resolve(serviceType) : null;
}
This is called the Service Locator pattern, and some consider it bad practice. By exposing Castle Windsor in this way, you have actually lost some of its benefits. In particular, your DepartmentsController
now depends on the Service Locator and its GetService
method. I won't cover all of the supposed disadvantages of Service Locators, but consider what happens when your application grows and you now have numerous classes (potentially all of them) dependent upon this single class.
Your third example improves upon the Service Locator pattern by making the container invisible to your class:
public DepartmentsController(IDepartmentRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
_repository = repository;
}
Notice how this version has no knowledge of the kernel / container or a service locator. Instead, we have made its true dependencies explicit in the constructor rather than the means to those dependencies. In fact, by writing your classes this way, you can construct entire class libraries that are ignorant of Castle Windsor and will work perfectly fine with Ninject, another DI framework, or no container at all, without modifying the code.
How you actually register your components (the difference between examples two and three) is partly a matter of scale.
container.Register(
Component.For<IDeliveryItemRepository>().ImplementedBy<DeliveryItemRepository>().LifestylePerWebRequest(),
Component.For<IDeliveryRepository>().ImplementedBy<DeliveryRepository>().LifestylePerWebRequest(),
Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>().LifestylePerWebRequest(),
...
is fine for a smaller application. If the number of classes grows, you have to stomach a never ending list of bindings or find a better method. One improvement is to favor convention over configuration: if Castle Windor assumes every IDeliverItemRepository
has a DeliveryItemRepository
implementation, the bindings above can be skipped. However, you haven't solved anything if most of your classes require exceptional configuration; you still have a long, omniscient kernel / container registration method.
Instead, you should probably explore something like your second example. This way, your ConfigureWindsor
method can use reflection to find any IWindsorInstaller
s present in your application without knowing about specific interfaces or implementations. You can break all of your bindings into separate modules (Ninject's name for this concept) that are discovered at runtime.
To address your last question: Castle Windsor won't know which of your N
implementations to choose without you telling it. You can accomplish this through a mixture of the concepts discussed above: primarily by convention, but with IWindsorInstaller
s when needed to specify important details like lifecycle and conditional bindings.
Best Answer
I just finished an article today about the repository pattern (with sample implementations).
The thing with most .NET ioc containers is that they support scoping. That is, they can create objects with a limited lifetime. That works very well with HTTP applications since the scope is the same as the lifetime of a HTTP request.
If you use ASP.NET MVC you can combine that with built in features of MVC to trigger the UoW if no errors where detected: http://blog.gauffin.org/2012/06/how-to-handle-transactions-in-asp-net-mvc3/
If you use any other kind of application I usually create a scope by myself (for instance to wrap a command):
The thing is that the repositories etc do not have to be aware of the unit of work (if you use databases in .NET). The UoW implementation can make sure that all OR/M or UoW implementation enlists all db commands in the transaction.