Why is MVC4 using the Service Locator Anti-Pattern

2019-01-30 17:47发布

问题:

After reading "Dependency Injection in .NET" by Mark Seemann I stay away from the Service Locator which is an anti-pattern.

Upon reading the release notes on MVC 4 I see:

Improved Inversion of Control (IoC) via DependencyResolver: Web API now uses the service locator pattern implemented by MVC’s dependency resolver to obtain instances for many different facilities.

Thus I'm left curious and confused why Microsoft would use a service locator in 2012.

回答1:

That's an implementation detail that you shouldn't care about. The important thing is that now that the Web API uses the DependencyResolver to resolve dependencies for many different facilities, you will be able to use a real dependency injection whenever you want to plug into those facilities. So in your code you will be using a real dependency injection. If Microsoft didn't use the DependencyResolver then it would have been you that must have used it (as a service locator anti-pattern) in your code in order to resolve dependencies when you want to implement some custom functionality. This would have been bad for you. Now it's bad for Microsoft but you don't care about them.

Thus I'm left curious and confused why Microsoft would use a service locator in 2012.

Because designing a framework is not the same as designing an application using a framework. There are some different things to take into consideration when designing a reusable framework such as ASP.NET MVC rather than just what's written in the books. Some example is to design the framework in such a way that a person using this framework will be able to take advantage of the best practices written in the books in his code using this framework.



回答2:

As Darin points out, ASP.NET MVC 4 is a Framework and is container agnostic. That's why it provides a service locator in the form of IDependencyResolver. This allows anyone to plug in their container of choice.

However, I wouldn't call this an anti pattern. This allows you to use the container of your choice, but it doesn't force you the application developer to use service location. If the framework forced the developer to use Service Location, then I would call it an anti-pattern. But the developer who builds an ASP.NET MVC application is free to use DI via constructor injection, property setup, or service location. It's their choice.

Look at all the ASP.NET MVC examples of dependency injection published by me or the ASP.NET MVC team. In pretty much all cases, they're using constructor injection. They're not using service location.

In fact, most of the ASP.NET MVC source code itself doesn't use service location to retrieve dependencies. There's a few key places where the MVC calls into the service locator for legacy APIs and such. But that's about it.