在我的控制器中,所有依赖项都是通过注入(在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是我的域层前面的应用程序层的服务.映射器接收域对象,并返回视图要使用的DTO.
我的理由是,从ViewModel represents only the data that you want to display on your view/page开始,我无法预见需要用其他东西替换Mapper的情况,或者这对测试不利.我也看不到任何其他Presentation Layer都可以重用此Mapper类,因为其他视图可能不同于Web演示.对我来说,感觉就像是控制器的一部分.
问题是,这正确吗?我需要通过依赖注入来接收Mapper吗?我需要为其定义一个接口吗?如果是这样,出于什么原因?我想遵守SOLID原则,但是我想知道它们是否以及如何在这里适用.
解决方法:
就个人而言,我建议注入您的Mapper实例.这正是IoC容器旨在管理的内容.
没有理由在您的控制器中实例化它,并且在其当前状态下违反了SOLID原理的开闭原理和控制反转.
使用IoC容器注入时,您将获得以下好处:
增强的可测试性
通过将Mapper实例注入到控制器中,您将能够为其创建模拟以编写更好的测试.虽然您可以像现在那样测试控制器,但是无法在任何条件下测试控制器内的映射器实例.
增强的可扩展性
如果您希望能够将构造函数参数传递给映射器,那么几个月后会发生什么?您将需要完成所有控制器操作并更新构造函数.通过将创建Mapper实例的职责传递给IoC容器,您可以创建一个配置点,这意味着可以在一个地方管理和配置对Mapper类的任何进一步的修改或更改.
对于大多数预计可以使用几个月以上的软件,您可以确定一件事-它会发生变化.尽管您可能看不到映射器实例现在发生更改的原因,但是以一种使您能够尽可能轻松地进行更改的方式设计软件是一种很好的做法.您必须更改的点点滴滴越多,最有可能破坏某些东西或引入错误.