Microsoft.Composition (Portable MEF): Dependency Injection and Service Locator via Convention
This post is part of mini series, which complete the full MEF series.
this post will go over Microsoft.Composition Dependency Injection and Service Locator using conventions.
in the previous post I describe hot to register types using convention, but in real world types often has
their own dependencies which should be satisfies (this is why the IoC process also called composition).
In order to satisfy those dependencies you can take different approaches:
The most common way of passing the dependencies is constructor-based injection where the dependencies
passes to the constructor. this common practice accepted by most IoC (including MEF).
Using this approach it’s quite easy to figure out which dependencies each component has.
It’s also easy to test the component without having to set-up any IoC framework.
The down-side of is that no mutual dependencies allowed.
even though mutual dependencies may not consider as best practice in most cases, when you compose
the component right, it can be quite powerful capability, for now, just consider a Logger that have to
read its setting before it become operational and the Setting that may have to write some log
(I will explain how to do it right on future post).
constructor base injection looks like this:
Setter injection is less popular and not supported on many IoC framework
but it’s easy to use, can support mutual dependencies (depend on the IoC framework, MEF do support it).
on some framework the setter must use public modifier which is kind of sucks,
but MEF does support private setters (Unfortunately this version of MEF[Microsoft.Composition]
don’t support private modifier so well).
this approach is native to MEF either by [Import] attribute or by convention.
the following code demonstrate the convention style.
personally I don’t like registering property by convention (without attribute), because:
a: it is too much work
b: you should be familiar with the class dependencies at the configuration level and it’s getting
out of sync really fast (after few refactoring). it is hard to maintain and seem to be the wrong
responsibility of the configuration.
because this version of MEF don’t handle composition private property so well (in some cases)
you can consider the following pattern in order to hide the dependencies from intellisence (kind of a trick):
The [EditorBrowsable(EditorBrowsableState.Never)] attribute will hide the property from intellisense
and you will get experience like with private modifier.
Another common approach is Service Locator. I believe that there is to much confusion between
Dependency Injection and Service Locator so I will share my view on this issue.
Service Locator is equals to Dependency Injection with additional level of abstraction.
while the Dependency Injection’s constructor is getting all dependencies,
the Service locator will get single parameter which can be use to resolve the dependencies.
the following snippet show the differences:
As you can see you can achieve the same functionality using both patterns,
yet there’re so many discussion of which pattern is better.
I will try to help with this decision by going over the strength and weakness of each pattern.
Dependencies injection strength and weakness:
Starting with the Dependencies injection, it is very straight forward and descriptive.
– you can figure the class dependencies from it’s signature.
– testing don’t need the IoC framework in order to satisfy the dependencies:
– the down side is that you may have classes with to many parameters
and maintainability may also be an issue (adding or removing class dependency may lead to
changes on derived class’s constructor and potentially break-down of many tests which
you should fix one by one) .
Service Locator strength and weakness:
– the constrictor always having single parameter and it much easier to apply new
class dependencies (easier maintainace).
– the down-side of it is that the signature don’t reflect the dependencies.
Which pattern to use?
Choosing the IoC pattern is very much matter of personal preference and I don’t think that
you can argue that one pattern is better than the other.
I’m usually using the Service Locator pattern, but for better usability I’m using extension method.
Extension methods can help with dependencies discoverability when using intellisense.
This is a common practice which also used by ASP.NET:
Everything starts with Use… is simply extension method, which define by ASP.NET (or extensions for ASP.NET).
This is how you do it with Service Locator over MEF.
the constructors at lines 21 and 28 is having the same parameters (therefore won’t compile)
in reality you have to choose which pattern you like like best.
I think that choosing single pattern is better for reducing confusion and maintain code consistency.
this post spoke about IoC pattern more than it was about MEF.
I was using MEF on the Service Locator pattern by using CompositionContext
which is something that MEF register by default (you don’t have to manually
register it), but you can do it with any other IoC quite easily.