我正在尝试使用 DDD 创建一个应用程序,实现Domain Events,使用Entity Framework和StructureMap进行依赖注入。
我创建了 UnitOfWork 和 Repositories 的抽象。很明显,IUnitOfWork实现封装了DbContext,所有实例都是通过StructureMap(Nested Container的per HTTP request)注入的,所以在所有repositories中注入(也注入)的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" });
所以我可以在像实体这样的域对象中使用它。
但要让它工作,我不仅需要访问我的容器实例(所有事件处理程序都在其中注册),我需要访问当前嵌套容器实例以共享相同的 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 存储在 HttpContext 中并从存储库中检索它。因此,存储库实例和 IUnitOfWork 实例将不同,但使用的 DbContext 将是相同的。
我不喜欢这个解决方案,因为我不想使用 HttpContext。
也许有某种方法可以获取当前请求的嵌套容器......
你能给我一点光吗?谢谢