Dependency Injection with Ninject, MVC 3 and using the Service Locator Pattern

Something that has been bugging me since I read an answer on another stackoverflow question (the precise one eludes me now) where a user stated something like "If you're calling the Service Locator, you're doing it wrong."

It was someone with a high reputation (in the hundred thousands, I think) so I tend to think this person might know what they're talking about. I've been using DI for my projects since I first started learning about it and how well it relates to Unit Testing and what not. It's something I'm fairly comfortable with now and I think I know what I'm doing.

However, there are a lot of places where I've been using the Service Locator to resolve dependencies in my project. Once prime example comes from my ModelBinder implementations.

Example of a typical model binder.

public class FileModelBinder : IModelBinder {
    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext) {
        ValueProviderResult value = bindingContext.ValueProvider.GetValue("id");

        IDataContext db = Services.Current.GetService<IDataContext>();
        return db.Files.SingleOrDefault(i => i.Id == id.AttemptedValue);
    }
}

not a real implementation - just a quick example

Since the ModelBinder implementation requires a new instance when a Binder is first requested, it's impossible to use Dependency Injection on the constructor for this particular implementation.

It's this way in a lot of my classes. Another example is that of a Cache Expiration process that runs a method whenever a cache object expires in my website. I run a bunch of database calls and what not. There too I'm using a Service Locator to get the required dependency.

Another issue I had recently (that I posted a question on here about) was that all my controllers required an instance of IDataContext which I used DI for - but one action method required a different instance of IDataContext. Luckily Ninject came to the rescue with a named dependency. However, this felt like a kludge and not a real solution.

I thought I, at least, understood the concept of Separation of Concerns reasonably well but there seems to be something fundamentally wrong with how I understand Dependency Injection and the Service Locator Pattern - and I don't know what that is.

The way I currently understand it - and this could be wrong as well - is that, at least in MVC, the ControllerFactory looks for a Constructor for a Controller and calls the Service Locator itself to get the required dependencies and then passes them in. However, I can understand that not all classes and what not have a Factory to create them. So it seems to me that some Service Locator pattern is acceptable...but...

  1. When is it not acceptable?
  2. What sort of pattern should I be on the look out for when I should rethink how I'm using the Service Locator Pattern?
  3. Is my ModelBinder implementation wrong? If so, what do I need to learn to fix it?
  4. In another question along the lines of this one user Mark Seemann recommended an Abstract Factory - How does this relate?

I guess that's it - I can't really think of any other question to help my understanding but any extra information is greatly appreciated.

I understand that DI might not be the answer to everything and I might be going overboard in how I implement it, however, it seems to work the way I expect it to with Unit Testing and what not.

I'm not looking for code to fix my example implementation - I'm looking to learn, looking for an explanation to fix my flawed understanding.

I wish stackoverflow.com had the ability to save draft questions. I also hope whoever answers this question gets the appropriate amount of reputation for answering this question as I think I'm asking for a lot. Thanks, in advance.

13
задан Community 23 May 2017 в 10:33
поделиться