【问题标题】:Using DI and IoC with ASP.MVC 3 how do I setup my Controllers to resolve new types correctly?在 ASP.MVC 3 中使用 DI 和 IoC 如何设置我的控制器以正确解析新类型?
【发布时间】:2012-02-16 00:09:43
【问题描述】:

我一直在阅读 Mark Seemann 的书 Dependency Injection in .NET 以及他关于 DI Composition Roots 的博客文章。

我正在重构我的 ASP.MVC 3 应用程序容器调用,从我的控制器中调用到组合根中。

过去我会像这样在控制器中解析类型。

[HttpGet]
public ActionResult Create()
{
    // Don't do this...
    var color = MvcApplication.Container.Resolve<IColor>();                           
    return View(color);
}

阅读 Mark 的书后,我意识到这不太理想,因此我设置了我的 MVC 应用程序,以便在应用程序启动时使用从 IControllerFactory 派生的类将存储库注入控制器,如 Mark 的书中第 7.2.1 节所述。

如果我不应该使用Service Locator 模式直接从我的 ASP.MVC 3 控制器调用 IoC 容器,我应该如何以及在哪里实例化新类型?每个控制器都是不同的,所以我想要一种解决新类型的通用方法。

我可以像这样直接实例化类型,但这会破坏目的。

[HttpGet]
public ActionResult Create()
{
   // Don't do this...
   var color = new Color();
   return View(color);
}

我是否应该将通用工厂与通用存储库一起注入我的控制器并将其用于新的创建类型?有没有更好的办法?

编辑

我意识到这与另一个 SO question 相似,但我的实体具有需要在将它们传递到视图之前解决的依赖关系。

【问题讨论】:

标签: .net asp.net-mvc-3 dependency-injection inversion-of-control


【解决方案1】:

您希望在应用程序启动时创建一个容器并在 global.asax(包括您的控制器)中注册服务。您还想为使用我刚刚描述的容器的 IControllerFactory 提供您自己的实现。通过设置属性 ControllerBuilder.Current.SetControllerFactory 通知应用程序使用新的控制器工厂。

更多详情:http://bradwilson.typepad.com/blog/2010/07/service-location-pt2-controllers.html

您不想在控制器操作中更新对象,相反,您的控制器应该依赖可以提供所需对象的服务。

一种方法如下

public interface IColorFactory
{
  IColor GetColor();
}

// this implementation is registered with the container
public class DefaultColorFactory : IColorFactory
{
  // this implementation is the only one that knows the details of the IColor implementation
  public IColor GetColor() {  return new Color(); } 
}

public class MyController : ControllerBase
{
  private readonly IColorFactory _colorFactory;
  public MyController(IColorFactory cf)
  {
    _colorFactory = cf;
  }

    [HttpGet]
    public ActionResult Create()
    {
      return View(_colorFactory.GetColor());
    }
}

【讨论】:

  • 我的问题不是如何在 MVC 中设置组合根,而是当我需要在控制器操作中新建对象时如何保持组合根的完整性。马克的书解释了如何设置它 - 我很好。
  • 根据 Mark Seemann 和您的回答,我将继续按照建议使用工厂模式。
【解决方案2】:

question 中有一些关于服务定位器使用的信息。

你总是可以通过Controller构造函数来处理依赖:

 public class HomeController : Controller
    {

    private readonly IColor _iColor;

    public HomeController(IColor iColor)
    {

    _iColorService = iColor;
    }

    [HttpGet]
    public ActionResult Create()
    {
       var color = _iColor;
       return View(color);
    }

    }

【讨论】:

  • 这是更好的答案,因为 IoC 容器应该是所有依赖项的工厂。只需确保使用功能完善的 DI 框架,如 StructureMap、Windsor 或类似框架,并正确注册依赖项。
  • @Beller 我不确定您的使用场景,但如果您查看本书的 DI 模式部分(从第 95 页开始),您会发现这个(构造函数注入)是最常见的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
  • 2014-01-17
  • 1970-01-01
相关资源
最近更新 更多