A meno che non sto equivoco il vostro intento e invece ho scelto per concentrarsi sulla semantica analizzerò questa affermazione "Ad esempio: ogni entità di dominio che ha bisogno di inviare una email dovrebbe dipendere da un'interfaccia IEmailService."
Devo dire che questo è su se stesso è un estremo bastardizzazione di DDD. Perché un'entità di dominio dovrebbe mai dipendere da un servizio di posta elettronica? IMO non dovrebbe. Non c'è alcuna giustificazione per questo.
Tuttavia ci sono operazioni aziendali in congiunzione con un'entità di dominio che richiederebbe la necessità di inviare e-mail. Dovresti avere la tua dipendenza IEmailService
contenuta in questa classe qui, non l'entità di dominio. Molto probabilmente questa classe rientrerà in uno dei pochi nomi quasi sinonimi: Modello, Servizio o Controller a seconda dell'architettura/livello in cui ti trovi.
A questo punto il tuo StructureMapControllerFactory
quindi automaticamente collegherà automaticamente tutto ciò che userebbe il IEmailService
.
Mentre potrei essere minorly oltre generalizzare è praticamente una pratica standard per avere entità del dominio essere Pocos o essere quasi pocos (per evitare la violazione del SRP) però spesso SRP è violata in entità del dominio per l'amor di serializzazione e validazione. Scegliere di violare l'SRP per quei tipi di preoccupazioni trasversali è più una posizione di credenza personale che una decisione "giusta" o "sbagliata".
Come follow-up finale se la tua domanda è sulla porzione di codice che funziona veramente in un servizio stand-alone sia web o OS based e come collegare le dipendenze da quello, una normale soluzione sarebbe prendere in carico il servizio a livello di base e applicare IOC allo stesso modo simile a quello fatto da StructureMapControllerFactory
in MVC. Come ottenere questo risultato dipende interamente dall'infrastruttura con cui stai lavorando.
Risposta:
Diciamo che avere IOrderConfirmService
che ha un metodo EmailOrderConfirmation(Order order)
. Si potrebbe finire con qualcosa di simile:
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);
}
}
si dovrebbe quindi avere la vostra classe OrderController
che sarebbe qualcosa di simile
public class OrderController : Controller
{
private readonly IOrderConfirmService _service;
public OrderController(IOrderConfirmService service)
{
_service= service;
}
public ActionResult Confirm()
{
_service.EmailOrderConfirmation(some order);
return View();
}
}
StrucutreMap sarà intrinsecamente costruire sei tutta la catena di architettura quando si utilizza il costruttore iniezione correttamente. Questa è la differenza fondamentale tra accoppiamento stretto e inversione del controllo. Quindi, quando StructureMapFactory va a creare il controller, la prima cosa che vedrà è che ha bisogno di IOrderConfirmService. A questo punto controllerà se è in grado di collegare direttamente IOrderConfirmService, il quale non può perché ha bisogno di IEmailService. Quindi controllerà se può collegare IEmailService e per argumentsake diciamo che può farlo. Quindi a questo punto costruirà EmailService, che quindi creerà MyOrderConfirmService e inserirà EmailService, quindi creerà OrderController e inserirà MyOrderConfirmService. Da qui deriva il termine inversione di controllo. StructureMap costruirà l'EmailService per primo nell'intera catena di dipendenze e terminerà per ultimo con il Controller. In una configurazione strettamente accoppiata questo sarà l'opposto in cui il Controller sarà costruito per primo e dovrà costruire il servizio aziendale e quindi costruire il servizio di posta elettronica. Il design strettamente accoppiato è molto fragile rispetto al CIO.
Chris sei morto. Mi sembrava di aver violato qualcosa iniettando "IEmailService" in entità di dominio. Supponendo che si tratti di un servizio di base, come/dove devo collegare le varie entità che dovranno utilizzare 'IEmailService'? Immagino di avere difficoltà a visualizzare come funzionerebbe. – ahsteele
Ha risposto al tuo commento. –
Ho apportato una piccola modifica al codice del costruttore del controller. – ahsteele