除非我误解了您的意图,而是选择专注于语义,否则我将剖析这句话“例如:每个需要能够发送电子邮件的域实体都应该依赖于 IEmailService 接口。”
我不得不争辩说,这本身就是对 DDD 的极端混蛋。为什么域实体需要依赖电子邮件服务?海事组织不应该。没有理由这样做。
但是,与需要发送电子邮件的域实体相关的业务操作。您应该将您的IEmailService
依赖项包含在此类中,而不是域实体中。此类很可能属于几个几乎同义的名称之一:模型、服务或控制器,具体取决于您所在的架构/层。
此时,您StructureMapControllerFactory
将正确地自动连接所有将使用IEmailService
.
虽然我可能略微过度概括,但将域实体设为 POCO 或接近 POCO(以避免违反 SRP)几乎是标准做法,但为了序列化和验证,域实体中经常违反 SRP。为这些类型的交叉关注选择违反 SRP 更多的是个人信仰立场,而不是“正确”或“错误”的决定。
作为最后的跟进,如果您的问题是关于真正在独立服务中运行的代码部分,无论是基于 Web 还是基于操作系统,以及如何连接依赖关系,一个正常的解决方案是在基础上接管该服务水平并以与StructureMapControllerFactory
MVC 中类似的方式对其应用 IOC 。如何实现这一点将完全取决于您正在使用的基础架构。
回复:
可以说你有IOrderConfirmService
which has a method 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);
}
}
然后,您的OrderController
课程将类似于
public class OrderController : Controller
{
private readonly IOrderConfirmService _service;
public OrderController(IOrderConfirmService service)
{
_service= service;
}
public ActionResult Confirm()
{
_service.EmailOrderConfirmation(some order);
return View();
}
}
当您正确使用构造函数注入时,StrucutreMap 将固有地构建您的整个架构链。这是紧耦合和控制反转之间的根本区别。因此,当 StructureMapFactory 开始构建您的控制器时,它首先会看到它需要 IOrderConfirmService。此时它会检查它是否可以直接插入 IOrderConfirmService,但它不能,因为它需要 IEmailService。所以它会检查它是否可以插入 IEmailService 并且为了争论可以说它可以。所以此时它将构建EmailService,然后构建MyOrderConfirmService并插入EmailService,最后构建OrderController并插入MyOrderConfirmService。这就是术语控制反转的来源。StructureMap 将在整个依赖链中首先构建 EmailService,最后以 Controller 结束。在紧密耦合的设置中,这将与首先构建控制器并且必须构建业务服务然后构建电子邮件服务的情况相反。与 IOC 相比,紧耦合设计非常脆弱。