patterncsharpMinor
Looking for advice - Dependency Injection over Service Locator in Mef
Viewed 0 times
locatordependencymeflookingadviceserviceforinjectionover
Problem
I'm wondering what people think about Dependency Injection vs Service Locator patterns. Specifically I'm using Prism with MEF. I'm also using the MVVM pattern.
So I have a service which I export. I also have a class which doesn't export its class type as I don't need that to be registered with MEF. This class is actually a View-Model which is assigned to a hierarchical data template inside a TreeView.
However the view-model needs to import an interface registered with MEF.
Now I have three possible ways to do this:
Here some example code to demonstrate.
Then the three possible implementation of the View-Model are:
Each of the tree-view items actually has an
So I have a service which I export. I also have a class which doesn't export its class type as I don't need that to be registered with MEF. This class is actually a View-Model which is assigned to a hierarchical data template inside a TreeView.
However the view-model needs to import an interface registered with MEF.
Now I have three possible ways to do this:
- Set an
[Import]on the interface and useComposePartsin the constructor to inject the dependency.
- Use
SerivceLocator.Currentpattern to get the instance of the service.
- Pass in the service interface on the constructor, which is kind of a manual dependency injection.
Here some example code to demonstrate.
public interface IFooService
{
}
[Export(typeof(IFooService))]
[PartCreationPolicy(CreationPolicy.Shared)]
class FooSevice : IFooService
{
}Then the three possible implementation of the View-Model are:
public class TreeItemVM_MefInjection
{
[Import]
public IFooService FooService { get; set; }
public TreeItemVM_MefInjection()
{
var catalog = new AssemblyCatalog
(System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
public class TreeItemVM_ServiceLocator
{
[Import]
public IFooService FooService { get; set; }
public TreeItemVM_ServiceLocator()
{
FooService = ServiceLocator.Current.GetInstance();
}
}
public class TreeItemVM_ManualInjection
{
public IFooService FooService { get; set; }
public TreeItemVM_ManualInjection(IFooService fooService)
{
FooService = fooService;
}
}Each of the tree-view items actually has an
ObservableCollection as the tree is hierarchical. Each ViewModel can create it's own children, based on tSolution
-
Service locator is an anti-pattern because it tends to create implicit dependencies which are not easy to see and usually cause grieve when trying to write unit tests. Especially your implementation which references what seems like a singleton instance which can cause additional problems (i.e. you need to take care to reset it between tests).
Avoid it.
-
I can't say much about the MEF injection but it seems roundabout having to write all that code. It also creates an implicit dependency which will probably cause grieve when unit testing your class and makes it directly dependent on MEF while there is no need for it.
Avoid it.
-
Clean and simple. Explicit dependency, easy to unit test and injection can be easily manged by any IoC container of your choice (Unity, Ninject, Windsor, etc.).
The way to go.
Service locator is an anti-pattern because it tends to create implicit dependencies which are not easy to see and usually cause grieve when trying to write unit tests. Especially your implementation which references what seems like a singleton instance which can cause additional problems (i.e. you need to take care to reset it between tests).
Avoid it.
-
I can't say much about the MEF injection but it seems roundabout having to write all that code. It also creates an implicit dependency which will probably cause grieve when unit testing your class and makes it directly dependent on MEF while there is no need for it.
Avoid it.
-
Clean and simple. Explicit dependency, easy to unit test and injection can be easily manged by any IoC container of your choice (Unity, Ninject, Windsor, etc.).
The way to go.
Context
StackExchange Code Review Q#35247, answer score: 5
Revisions (0)
No revisions yet.