如何使用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。
也许有一些方法来获取当前请求的嵌套容器...
你能告诉我一些光吗? 谢谢
看着StructureMap文档,我发现这种方式。
- 使用全局根容器来创建事件处理程序实例。
- 添加对structuremap.web包的引用。
-
配置的UnitOfWork(中的DbContext其实)注册表,在未来的道路生命周期设置为HttpContextLifecycle:
var container = new Container(_ => { _.For(typeof (IUnitOfWork)).Use(typeof (EFUnitOfWork)) .SetLifecycleTo(new HttpContextLifecycle());
我不完全相信这个解决办法,但比实施更好我自己的UnitOfWork/DbContext存储在HttpContext上。
在更改持续之前,您绝不应该发布事件。 –
我认为这取决于我们想要发布的事件类型。 –
如果您承担发布虚假事件 –