依赖注入与Ninject,MVC 3,并使用​​Service Locator模式 [英] Dependency Injection with Ninject, MVC 3 and using the Service Locator Pattern

查看:114
本文介绍了依赖注入与Ninject,MVC 3,并使用​​Service Locator模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

东西一直缠着我,因为我读了另一个计算器问题的答案(的precise 1躲开我现在)其中一个用户说类似如果你调用了服务定位器,你'再做错了。

这是有人用很高的声誉(在十万,我认为),所以我倾向于认为这个人可能知道他们在说些什么。我一直在使用DI为我的项目,因为我第一次开始学习它以及它如何涉及到单元测试,什么不是。这件事情我相当满意,现在我的认为的,我知道我在做什么。

不过,也有很多,我一直在使用的服务定位器来解决我的项目依赖的地方。一旦典型的例子来自于我ModelBinder的实现。

一个典型的模型绑定的例子。

 公共类FileModelBinder:IModelBinder {
    公共对象BindModel(ControllerContext controllerContext,
                            ModelBindingContext的BindingContext){
        ValueProviderResult值= bindingContext.ValueProvider.GetValue(ID);        IDataContext DB = Services.Current.GetService< IDataContext>();
        返回db.Files.SingleOrDefault(ⅰ= GT; i.Id == id.AttemptedValue);
    }
}

不是一个真正的实现 - 只需一个简单的例子

由于ModelBinder的实施需要当粘合剂的第一个新实例的要求,这是不可能的使用依赖注入的构造这个特定的实现。

这是这种方式有很多我的班。另一个例子是,每当缓存对象在我的网站到期运行的方法的缓存过期进程。我跑了一堆的数据库调用,什么不可以的。有太多我使用一个服务定位器,以获得所需的依赖关系。

最近,我(我张贴的问题就到这里约)的另一个问题是,我所有的控制器需要我用DI为IDataContext的一个实例 - 但是的有一个的操作方法所需的不同实例IDataContext。幸运的是Ninject来到一个叫依赖救援。然而,这种感觉就像一个杂牌,而不是真正解决问题。

我想我至少明白顾虑合理地分离的概念,但似乎有一些根本性的错误我所理解的依赖注入和服务定位器模式 - 我不知道那是什么<。 / p>

目前,我的理解是 - 这可能是错的,以及 - 是,至少在MVC中,的ControllerFactory查找的控制器的构造函数,并调用服务定位器本身来获得所需要的依赖关系,然后将它们传递英寸不过,我可以理解,并非所有的类并没有什么有一个工厂来创建它们。所以,在我看来,有些Service Locator模式是可以接受的...但是...


  1. 在当前是不是可以接受?

  2. 我应该看出来,当我应该重新思考我如何使用Service Locator模式?
  3. 什么样的​​格局
  4. 是我ModelBinder的执行错了吗?如果是这样,我需要什么学习解决?

  5. 在沿着这一个用户马克·塞曼推荐一个抽象工厂的线条另一个问题 - 如何这与?

我想这就是它 - 我真的不能相信任何其他的问题,帮助我理解,但任何额外的信息,大大AP preciated

据我所知,DI可能不是一切问题的答案,我可能会在海里我如何实现它走了,但是,它似乎工作,我希望它与单元测试的方式,什么不是。

我不是找code来解决我的示例实现 - 我希望学习,寻找一个解释来解决我的理解存在缺陷

我希望stackoverflow.com不得不救的问题草案的能力。我也希望无论谁回答了这个问题得到声誉适量的,因为我觉得我问了很多回答这个问题。谢谢你,在前进。


解决方案

考虑以下几点:

 公共类MyClass的
{
  IMyInterface的_myInterface;
  IMyOtherInterface _myOtherInterface;  公共MyClass的(IMyInterface的MyInterface的,IMyOtherInterface myOtherInterface)
  {
    //富    _myInterface = MyInterface的;
    _myOtherInterface = myOtherInterface;
  }
}

通过这个设计,我能够EX preSS为我喜欢的类型的依赖需求。该类型本身不负责知道如何实例化任何依赖关系,它们是由什么解决机制用于[典型IoC容器]给它(注射)。鉴于:

 公共类MyClass的
{
  IMyInterface的_myInterface;
  IMyOtherInterface _myOtherInterface;  公共MyClass的()
  {
    //酒吧    _myInterface = ServiceLocator.Resolve&LT; IMyInterface的&GT;();
    _myOtherInterface = ServiceLocator.Resolve&LT; IMyOtherInterface&GT;();
  }
}

我们的类现在依赖于创建specfic实例,但通过委托给服务定位器。从这个意义上讲,服务定位也算是一种的反模式的,因为你没有揭露的依赖,但你允许它可以通过编译陷入泡成运行时问题。 (很好看的是这里)。你隐藏的复杂性。

一个或另一个之间的选择真的取决于你之上,它提供的服务是什么建筑。通常情况下,如果你是从头开始构建一个应用程序,我会选择DI所有的时间。它提高了可维护性,促进了模块化和使测试类型轻松许多。但是,以ASP.NET MVC3作为一个例子,你可以很容易地实现SL作为其烤到设计中。

您可以随时去一个复合材料的设计,你可以使用的IoC / DI与SL,就像使用公共服务定位​​器。你部件可以通过DI进行接线,而是通过SL曝光。你甚至可能会引发成分进入组合,并使用类似的托管扩展性框架(它本身支持DI,但也可以连接到其他的IoC容器或服务定位器)。这是一个很大的设计作出选择,一般我的建议是对的IoC / DI在可能的情况。

您具体的设计,我不会说的是错的。在这种情况下,您的code是不负责创建模型粘合剂本身的一个实例,这是最高的框架,所以你必须在没有控制的您的服务定位器的使用可以大概很容易地更改访问IoC容器。的但是致电解决IoC容器上......你会不会考虑该服务的位置?动作

使用抽象工厂模式的工厂是一家专业创造特定类型。你不分辨率注册类型,其本质就是注册一个抽象工厂和建立你可能需要的任何类型。与服务定位它的设计的定位服务的并返回这些实例。从一个角度公约点相似,但在行为非常不同的

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.

解决方案

Consider the following:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass(IMyInterface myInterface, IMyOtherInterface myOtherInterface)
  {
    // Foo

    _myInterface = myInterface;
    _myOtherInterface = myOtherInterface;
  }
}

With this design I am able to express the dependency requirements for my type. The type itself isn't responsible for knowing how to instantiate any of the dependencies, they are given to it (injected) by whatever resolving mechanism is used [typically an IoC container]. Whereas:

public class MyClass
{
  IMyInterface _myInterface;
  IMyOtherInterface _myOtherInterface;

  public MyClass()
  {
    // Bar

    _myInterface = ServiceLocator.Resolve<IMyInterface>();
    _myOtherInterface = ServiceLocator.Resolve<IMyOtherInterface>();
  }
}

Our class is now dependent on creating the specfic instances, but via delegation to a service locator. In this sense, Service Location can be considered an anti-pattern because you're not exposing dependencies, but you are allowing problems which can be caught through compilation to bubble up into runtime. (A good read is here). You hiding complexities.

The choice between one or the other really depends on what your building on top of and the services it provides. Typically if you are building an application from scratch, I would choose DI all the time. It improves maintainability, promotes modularity and makes testing types a whole lot easier. But, taking ASP.NET MVC3 as an example, you could easily implement SL as its baked into the design.

You can always go for a composite design where you could use IoC/DI with SL, much like using the Common Services Locator. You component parts could be wired up through DI, but exposed through SL. You could even throw composition into the mix and use something like the Managed Extensibility Framework (which itself supports DI, but can also be wired to other IoC containers or service locators). It's a big design choice to make, generally my recommendation would be for IoC/DI where possible.

Your specific design I wouldn't say is wrong. In this instance, your code is not responsible for creating an instance of the model binder itself, that's up to the framework so you have no control over that but your use of the service locator could probably be easily changed to access an IoC container. But the action of calling resolve on the IoC container...would you not consider that service location?

With an abstract factory pattern the factory is specialised at creating specific types. You don't register types for resolution, you essentially register an abstract factory and that builds any types that you may require. With a Service Locator it is designed to locate services and return those instances. Similar from an convention point of view, but very different in behaviour.

这篇关于依赖注入与Ninject,MVC 3,并使用​​Service Locator模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆