ahs*_*ele 7 c# domain-driven-design ioc-container inversion-of-control autowired
在我最新的ASP.NET MVC 2应用程序中,我一直在尝试将域驱动设计(DDD),单一责任原则(SRP),控制反转(IoC)和测试驱动开发(TDD)的概念付诸实践.作为一个架构示例,我一直关注Jeffery Palermo的" Onion Architecture ",它在ASP.NET MVC 2 in Action中得到了极大的扩展.

虽然,我已经开始成功地应用这些原则中的大多数(一些?),但我错过了这个难题的关键部分.我无法确定将服务层自动连接到域实体的最佳机制.
例如:需要能够发送电子邮件的每个域实体都应该依赖于IEmailService接口.从我的阅读中,揭示这种依赖性的最佳实践是使用构造函数注入.在我的UI层中,我使用StructureMapControllerFactoryfrom ASP.NET MVC Contrib对存储库接口实现执行类似的注入.
我感到困惑的是,将必要服务的注入自动连接到域实体的最佳机制是什么?域实体是否应该以这种方式注入?IEmailService如果我不将其注入域实体,我将如何使用?
额外的Stack Overflow问题是很棒的DDD,SRP,IoC,TDD参考:
除非我误解了您的意图,而是选择专注于语义,否则我将剖析这句话“例如:每个需要发送电子邮件能力的域实体都应该依赖于 IEmailService 接口。”
我不得不争辩说,这本身就是对 DDD的极端混杂。为什么域实体需要依赖电子邮件服务?IMO 不应该。没有理由这样做。
但是,有一些业务操作与需要发送电子邮件的域实体相结合。您应该将您的IEmailService依赖项包含在此类中,而不是域实体中。此类很可能属于几个几乎同义的名称之一:模型、服务或控制器,具体取决于您所在的架构/层。
此时,您StructureMapControllerFactory将正确地自动连接所有将使用IEmailService.
虽然我可能稍微过度概括,但让域实体成为 POCO 或接近 POCO(以避免违反 SRP)几乎是标准做法,但是为了序列化和验证,域实体中经常违反 SRP。选择违反 SRP 来解决这些类型的交叉问题更多的是个人信仰立场,而不是“正确”或“错误”的决定。
作为最后的跟进,如果您的问题是真正在独立服务中运行的代码部分,无论是基于 Web 还是基于操作系统,以及如何从中连接依赖项,正常的解决方案是在基础上接管服务级别并以与StructureMapControllerFactoryMVC 中相同的方式应用 IOC 。如何实现这一点将完全取决于您正在使用的基础架构。
回复:
假设你有IOrderConfirmService一个方法EmailOrderConfirmation(Order order)。你最终会得到这样的结果:
public class MyOrderConfirmService : IOrderConfirmService
{
private readonly IEmailService _mailer;
public MyOrderConfirmService(IEmailService mailer)
{
_mailer = mailer;
}
public void EmailOrderConfirmation(Order order)
{
var msg = ConvertOrderToMessage(order); //good extension method candidite
_mailer.Send(msg);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你会有你的OrderController课程,就像
public class OrderController : Controller
{
private readonly IOrderConfirmService _service;
public OrderController(IOrderConfirmService service)
{
_service= service;
}
public ActionResult Confirm()
{
_service.EmailOrderConfirmation(some order);
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
当您正确使用构造函数注入时, StrucutreMap 将固有地构建您的整个架构链。这是紧耦合和控制反转之间的根本区别。因此,当 StructureMapFactory 开始构建您的控制器时,它会看到的第一件事是它需要 IOrderConfirmService。此时它会检查是否可以直接插入 IOrderConfirmService 而它不能,因为它需要 IEmailService。所以它会检查它是否可以插入 IEmailService 并且为了争论可以说它可以。所以此时它会构建EmailService,然后它会构建MyOrderConfirmService 并插入EmailService,最后构建OrderController 并插入MyOrderConfirmService。这就是控制反转一词的由来。StructureMap 将首先在整个依赖链中构建 EmailService,最后以 Controller 结束。在紧密耦合的设置中,这将是相反的,首先构建控制器,必须构建业务服务,然后构建电子邮件服务。与 IOC 相比,紧耦合设计非常脆弱。