如何使用StructureMap和当前请求容器从域对象发布域事件?

问题描述:

我试图创建与DDD的应用,实现域事件,使用实体框架和依赖注入StructureMap如何使用StructureMap和当前请求容器从域对象发布域事件?

我创建了UnitOfWork和Repositories的抽象。显然,IUnitOfWork实现封装了DbContext,并且所有实例都由StructureMap(Nested Container的每个HTTP请求)注入,所以注入到所有存储库(也是注入的)中的IUnitOfWork是同一个实例(出于同样的原因,每个请求都创建一个DbContext实例)。

的UnitOfWork实现是这样的...

public class EFUnitOfWork : IUnitOfWork, IDisposable 
{ 
    public EFUnitOfWork(ApplicationDbContext dbContext) 
    { 
     Context = dbContext; 
    } 

    ... 

...和仓库都喜欢..

public class BaseRepository<T, TId> : IRepository<T, TId>, IAggregateRoot 
{ 
    private readonly IUnitOfWork _unitOfWork; 

    // All the repositories created are automaticaly injected 
    // with the same IUnitOfWork instance during the request. 
    public BaseRepository(IUnitOfWork unitOfWork) 
    { 
     _unitOfWork = unitOfWork; 
    ... 

这一切运作良好,我可以使用上下文管理我的变化我的IUnitOfWork实例。

public class UsersService : IUsersService 
{ 

     private readonly IUnitOfWork _unitOfWork; 
     private readonly IUserRepository _userRepository; 

     public UsersService(IUnitOfWork unitOfWork, IUserRepository userRepository) 
     { 
      _unitOfWork = unitOfWork; 
      _userRepository = userRepository; 
     } 

     public override CreateUserUseCaseResult HandleExecute(CreateUserUseCaseRequest input) 
     { 
      var user = Mapper.Map<User>(input.User); 
      _userRepository.Insert(user); 

      ... 

      _unitOfWork.SaveChanges(); 

      return new CreateUserUseCaseResult 
      { 
       User = Mapper.Map<UserViewModel>(user) 
      }; 
     } 
    } 

的问题

我想实现域事件,而这个想法是有方法的静态类发布的事件是这样的:

DomainEvents.Publish(new TheDomainEvent() { Data = "something" }); 

所以我可以在Entities等域对象中使用它。

但它的工作我不仅需要访问我的容器实例(所有事件处理程序都注册),我需要访问当前嵌套容器实例共享相同的IUnitOfWork实例(我不需要IUnitOfWork直接,但我需要在所有存储库中注入相同的实例),因此可以在相同的DbContext上执行事件处理程序内的任何操作)。

所以...我怎样才能有一个发布方法的静态类,在域中可用?

现在,我临时解决了在服务上注入一个IDomainBus实例的问题,所以当前的嵌套容器用于创建事件处理程序实例。

public class SomeService : ISomeService 
{ 
     private readonly IDomainBus _domainBus; 

     public UsersService(IDomainBus domainBus, ...) 
     { 
      _domainBus= domainBus; 
     } 

     public void PerformSomeOperation(OperationRequest data) 
     { 
      ... 

      _domainBus.Publish(new SomeOperationPerformed() { Data = data }); 

      ... 

但是,如果我想从一个域实体像这里面发布事件,我不能使用此解决方案:

public class User : IEntity 
{ 
    public User() { } 

    public void UpdatePassword(string newPassword) 
    { 
     ... 

     DomainEvents.Publish(new UserPasswordUpdatedEvent() { User = this }); 

     ... 
    } 

一个可能的解决方案...

一可能的解决方案是将DbContext存储在HttpContex中并从存储库中的那里检索它。 因此,repositoriy实例和IUnitOfWork实例将会不同,但使用的DbContext将是相同的。

我不喜欢这个解决方案,因为我不想使用HttpContext。

也许有一些方法来获取当前请求的嵌套容器...

你能告诉我一些光吗? 谢谢

+0

在更改持续之前,您绝不应该发布事件。 –

+0

我认为这取决于我们想要发布的事件类型。 –

+0

如果您承担发布虚假事件 –

看着StructureMap文档,我发现这种方式。

  • 使用全局根容器来创建事件处理程序实例。
  • 添加对structuremap.web包的引用。
  • 配置的UnitOfWork(中的DbContext其实)注册表,在未来的道路生命周期设置为HttpContextLifecycle:

    var container = new Container(_ => 
    { 
        _.For(typeof (IUnitOfWork)).Use(typeof (EFUnitOfWork)) 
         .SetLifecycleTo(new HttpContextLifecycle()); 
    

我不完全相信这个解决办法,但比实施更好我自己的UnitOfWork/DbContext存储在HttpContext上。