HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Looking for advice - Dependency Injection over Service Locator in Mef

Submitted by: @import:stackexchange-codereview··
0
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:

  • Set an [Import] on the interface and use ComposeParts in the constructor to inject the dependency.



  • Use SerivceLocator.Current pattern 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 t

Solution

-
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.