dashCommerce V.Next - Dependency Injection / IoC August 4, 2008
Posted by chriscyvas in Coding, Open Source, dashCommerce.trackback
We’ve already started doing some refactoring of dashCommerce for V.Next. Right now, I have been doing the work on my code base for dashCommerce.com because I usually guinea pig that first to see how stuff is going to work. With the next rev, we are going to be introducing some Dependency Injection and IoC in order to loosen the application up. I mentioned this in dashCommerce and a crowbar.
In the Web project I have a ServiceRegistry class that simply loads the “Store” container and then the services are available off the ServiceRegistry. So, there are calls right now, like this:
lblRetailPriceAmount.Text = ServiceRegistry.CurrencyService.GetConvertedAmount(_product.RetailPrice, convertCode);
- and -
productCollection = ServiceRegistry.CatalogService.FetchProductsByCategoryId(categoryId) as ProductCollection;
These services then use the respective cache to pull the objects / values. So, the call stack looks like this:
CatalogService : ICatalogService
calls to — > CategoryCache and ProductCache
calls to –> CategoryController and ProductController
CurrencyService : ICurrencyService
calls to –> CurrencyRateCache
calls to –> CurrencyService
Do you see anything wrong with this?
I’ve also started moving all of the interfaces to a separate assembly in order to decrease the dependencies. Logically, the only reference Web should have is to the assembly that contains the interfaces while the dependency injection / IoC will take care of building up the services. Also, Store would also have a ServiceRegistry class that builds up any of the Core stuff that is required.
What do you think? Suggestions, comments, etc????
Looks more like a service locator than “pure” DI. It works, but i prefer constructor injection (never got around to setter injection). It makes coupling a bit looser and dependencies more explicit (i simply have to look at the constructor to know whats required). It also permits for optional dependencies (simply have ctor signatures without the optional dependencies). Much better is that the DI framework takes care of all the wiring, and upfront we know we have a usable object, dependencies satsfied, or we get fat nasty exceptions.
Yes, I understand - and it probably is a ServiceLocator in actuality - kind of - as the code looks like this:
public static class ServiceRegistry {
#region Member Variables
private static IDependencyResolver dependencyResolver = new UnityDependencyResolver("Store");
#endregion
public static ICatalogService CatalogService {
get {
return dependencyResolver.Resolve("catalogService");
}
}
public static ICurrencyService CurrencyService {
get {
return dependencyResolver.Resolve("currencyService");
}
}
}
We definitely want to be able to swap out at the service layers and they don’t have too many dependencies outside of themselves - what they do have is built up via the providers. Maybe this is a poor example or am I missing something?
Ok, so this isn’t really a ServiceLocator - it just plays one on TV.
I was trying to avoid having ICatalogService catalogService = resolver.Resove() all over the place. Good idea? Bad? Why? Why not?
lblRetailPriceAmount.Text = ServiceRegistry.CurrencyService.GetConvertedAmount(_product.RetailPrice, convertCode);
Lets encapsulate this logic in a composite label control. What do you think?
We can use this method for other things like localized resources.