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 useComposeParts
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<IFooService>();
}
}
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 the model data it uses (this is not shown in the above examples just to keep them simple).
So my issues with each of these are:
- It seems a lot of code to write to get automatic injection and I'm worried about the performance of creating a catalog and container temporarily. Is this OK to do it like this?
- The service locator seems easier but I've read that the service locator is an anti-pattern. Should I be concerned with this?
- The last one will give better performance as each instance just passes the
IFooService
interface on the constructor, and can pass it down to it's children when they are instantiated. However if I want to add more dependency injection latter on I need to change the constructor so maybe automatic injection or service locator maybe better.
So what would people say is the best method? Is there is a defined best practices method to follow? Are all the methods valid is it is up to the company coding standards to define the pattern to use?
Obviously the TreeItems
are just normally instanced with new. I don't want these to be exported to MEF as that is overkill and nothing outside of the class library needs to know about them. They are just normal class that need to have MEF dependency injection or find MEF registered interfaces.
Anyone have an opinion on the most desirable solution and any gotchas I should be aware of? I'm sure there are other possible solutions to this as well. Any info would be appreciated.