maandag 18 juni 2007

Dependency Injection versus Service Locators

When I was driving home from work, I have been thinking: when an object (entity) needs a reference to a repository for instance, to get some work done, how do you get a reference to that dependency (in this case, the repository) ?
Do you use dependency injection, or do you use a service locator ? When to choose what ? What are the advantages / disadvantages over both approaches ?

For example, suppose you have a 'Customer' class; this class has a property 'Status' which says whether the Customer is a 'Gold Customer', a 'Badly Paying Customer' or a 'Normal Customer'.
In order to determine to which 'state' a specific Customer belongs to, it might be necessary to retrieve some information out of a datastore. In this case, it could be necessary for instance to retrieve some invoice information regarding this customer.
(A Gold Customer for instance, is a Customer who has ordered for a specific amount of goods in a certain period, while a Bad Payer might be some-one who has overdue invoices).
So, a reference to an instance of IInvoiceRepository must be given to the Customer object.
The question now is, how do you give this dependency to the Customer object ?

Do you use 'Dependency Injection', and give this dependency via a constructor or a property to the Customer instance, like this:

Customer c = customerRepository.GetCustomer (5);
c.InvoiceRepository = repositoryFactory.CreateInvoiceRepository();

Or, should you leave this responsability to the Customer object ? In other words: let the Customer instance search for the correct IInvoiceRepository using a service locator. This could then be done in the Status property of the Customer class:

public CustomerStatus Status
{
get
{
IInvoiceRepository ir = DomainSettings.Instance.RepositoryLocator.GetInvoiceRepository();
...
return status;
}
}

In this case, the 'RepositoryLocator' can decide which implementation of IInvoiceRepository it has to create and return based on a value in a config file for instance.

Anyway, when do you choose for which option ? What are the advantages /disadvantages of both concepts ? In which situation do you favor the one over the other ?

I hope that some smart people can enlighten me about this matter. :)