我的Mapper类应该注入我的控制器还是可以直接实例化?

时间:2015-09-27 22:48:05

标签: c# asp.net-mvc dependency-injection mapping solid-principles

在我的控制器中,所有依赖关系都是通过注入接收到Dependency inversion principle之后的,除了一个Mapper类,它由构造函数实例化:

public class HomeController : Controller
{
    private readonly ISomeAppService SomeAppService;
    private readonly Mapper Mapper;

    public HomeController(ISomeAppService someAppService)
    {
        SomeAppService = someAppService;
        Mapper = new Mapper();
    }

    public ActionResult Index()
    {
        var someList = SomeAppService.GetSomeList();
        var someListDTO = Mapper.Map(someList);
        return View(new HomeIndexViewModel(someListDTO));
    }

SomeAppService是我的域层前面的应用层服务。 Mapper接收域对象并返回视图使用的DTO。

我的理由是,由于ViewModel represents only the data that you want to display on your view/page,我无法预见任何我需要用其他东西替换Mapper的情况,或者这对于测试来说可能是坏的。我也看不到这个Mapper类在任何其他表示层上被重用,因为其他视图可能与Web表示不同。对我而言,它是控制器的一部分。

问题是,这是正确的吗?我是否需要通过依赖注入接收Mapper?我需要为它定义一个接口吗?如果是这样,原因是什么?我想遵守SOLID原则,但我想知道它们是否以及如何适用于此。

2 个答案:

答案 0 :(得分:3)

我个人建议注入Mapper实例。这正是IoC Containers旨在管理的内容。

没有理由在控制器中实例化它,并且当前状态违反了开放原则和SOLID原则控制的反转。

使用IoC容器注入时所获得的好处是:

提高可测试性

通过将Mapper实例注入控制器,您将能够为其创建模拟以编写更好的测试。虽然您可以像现在一样测试控制器,但是您无法在控制器内测试任何条件下的映射器实例。

提高了可扩展性

如果您希望能够将构造函数参数传递给映射器,几个月内会发生什么?您需要完成所有控制器操作并更新构造函数。通过将创建Mapper实例的职责交给IoC容器,您可以创建单个配置点,这意味着可以在一个位置管理和配置对mapper类的任何进一步修改或更改。

对于大多数预期存活时间超过几个月的软件,您可以确定一件事 - 它会发生变化。虽然您可能没有看到映射器实例立即更改的原因,但是以一种使您能够尽可能轻松地进行更改的方式设计软件是一种很好的做法。你必须改变的点点滴滴,最有可能是你破坏或引入错误的机会。

答案 1 :(得分:0)

除了@JoeMighty给出的所有好处之外,我还要补充一点,通过在控制器中注入Mapper,可以外化Mapper.Map定义,释放出那个责任的控制器。此外,您可以通过控制注入的Mapper的生命周期来缓存映射定义,因此Mapper不必在每个请求上创建定义。