java ddd 领域事件_DDD实践:领域事件

要求:修改good表,添加 organization

基础定义

用于引发和调度事件的延迟方法 AddDomainEvent

Domain\SeedWork\Entity.cs

public abstract class Entity

{

int? _requestedHashCode;

T _Id;

public virtual T Id

{

get

{

return _Id;

}

protected set

{

_Id = value;

}

}

private List _domainEvents;

public IReadOnlyCollection DomainEvents => _domainEvents?.AsReadOnly();

public void AddDomainEvent(INotification eventItem)

{

_domainEvents = _domainEvents ?? new List();

_domainEvents.Add(eventItem);

}

public void RemoveDomainEvent(INotification eventItem)

{

_domainEvents?.Remove(eventItem);

}

public void ClearDomainEvents()

{

_domainEvents?.Clear();

}

public bool IsTransient()

{

return Id.ToString() == default(T).ToString();

}

public override bool Equals(object obj)

{

if (obj == null || !(obj is Entity))

return false;

if (Object.ReferenceEquals(this, obj))

return true;

if (this.GetType() != obj.GetType())

return false;

Entity item = (Entity)obj;

if (item.IsTransient() || this.IsTransient())

return false;

else

return item.Id.ToString() == this.Id.ToString();

}

public override int GetHashCode()

{

if (!IsTransient())

{

if (!_requestedHashCode.HasValue)

_requestedHashCode = this.Id.GetHashCode() ^ 31; // XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx)

return _requestedHashCode.Value;

}

else

return base.GetHashCode();

}

public static bool operator ==(Entity left, Entity right)

{

if (Object.Equals(left, null))

return (Object.Equals(right, null)) ? true : false;

else

return left.Equals(right);

}

public static bool operator !=(Entity left, Entity right)

{

return !(left == right);

}

}

聚合根

Goods.cs

public class Goods: Entity, IAggregateRoot

{

public string CreatedBy { get; private set; }

public DateTime? CreatedTime { get; private set; }

public string ModifiedBy { get; private set; }

public DateTime? ModifiedTime { get; private set; }

public string GoodsName { get; private set; }

public int? GoodsNum { get; private set; }

public Goods(string createdBy, DateTime? createdTime, string modifiedBy, DateTime? modifiedTime, string goodsName, int? goodsNum)

{

CreatedBy = createdBy;

CreatedTime = createdTime;

ModifiedBy = modifiedBy;

ModifiedTime = modifiedTime;

GoodsName = goodsName;

GoodsNum = goodsNum;

}

public void StockAddedToGoods()

{

AddDomainEvent(new StockAddedToGoodsDomainEvent()); //加入事件列表

}

public void SetModified()

{

ModifiedBy = "aaaaa";

ModifiedTime = DateTime.Now;

}

}

请注意 AddDomainEvent 方法的唯一功能是将事件添加到列表。 尚未调度任何事件,尚未调用任何事件处理程序。

你需要在稍后将事务提交到数据库时调度事件。 如果使用 Entity Framework Core,意味着在 EF DbContext 的 SaveChanges 方法中,如以下示例所示:

// EF Core DbContext

public class SampleContext : DbContext, IUnitOfWork

{

// ...

public async Task SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken))

{

// Dispatch Domain Events collection.

// Choices:

// A) Right BEFORE committing data (EF SaveChanges) into the DB. This makes

// a single transaction including side effects from the domain event

// handlers that are using the same DbContext with Scope lifetime

// B) Right AFTER committing data (EF SaveChanges) into the DB. This makes

// multiple transactions. You will need to handle eventual consistency and

// compensatory actions in case of failures.

await _mediator.DispatchDomainEventsAsync(this);

// After this line runs, all the changes (from the Command Handler and Domain

// event handlers) performed through the DbContext will be committed

var result = await base.SaveChangesAsync();

}

}

Organization.cs

public class Organization:

Entity, IAggregateRoot

{

public string CreatedBy { get; set; }

public DateTime CreatedTime { get; set; }

public string ModifiedBy { get; set; }

public DateTime ModifiedTime { get; set; }

public string Name { get; set; }

private Organization() { }

public Organization(Guid id, string name, string createdBy, DateTime createdTime, string modifiedBy,DateTime modifiedTime)

{

Id = id;

Name = name;

CreatedBy = createdBy;

ModifiedBy = modifiedBy;

ModifiedTime = modifiedTime;

AddDomainEvent(new OrganizationCreatedDomainEvent(name, id));

}

}

CQRS

34d63b80298513122a69cfe11a10dede.png

1.创建命令

[DataContract]

public class UpdateGoodsAndAddStockCommand : IRequest

{

[DataMember]

public Guid Id { get; set; }

[DataMember]

public string CreatedBy { get; private set; }

[DataMember]

public string GoodsName { get; private set; }

[DataMember]

public int GoodsNum { get; private set; }

}

2.创建处理

public class UpdateGoodsAndAddStockCommandHandler: IRequestHandler

{

private readonly IGoodsRepository _goodsRepository;

private readonly IMediator _mediator;

public UpdateGoodsAndAddStockCommandHandler(IGoodsRepository goodsRepository, IMediator mediator)

{

_goodsRepository = goodsRepository;

_mediator = mediator;

}

public async Task Handle(UpdateGoodsAndAddStockCommand request, CancellationToken cancellationToken)

{

var good = await _goodsRepository.GetAsync(request.Id);

good.SetModified(); //赋值修改人和修改时间,

good.StockAddedToGoods(); //添加 Stock 事件

return await _goodsRepository.UnitOfWork.SaveEntitiesAsync();

}

}

3.使用 IoC 的域事件调度程序

public class MediatorModule : Autofac.Module

{

protected override void Load(ContainerBuilder builder)

{

builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly)

.AsImplementedInterfaces();

// Register all the Command classes (they implement IRequestHandler) in assembly holding the Commands

builder.RegisterAssemblyTypes(typeof(CreateOrderCommand).GetTypeInfo().Assembly)

.AsClosedTypesOf(typeof(IRequestHandler));

//这里

builder.RegisterAssemblyTypes(typeof(UpdateGoodsAndAddStockCommand).GetTypeInfo().Assembly)

.AsClosedTypesOf(typeof(IRequestHandler))

// Other registrations ...

}

}

36dba42c83db831fb375e11ff561827d.png

事件列表

1c297e45f4a7989a5eae51b63f0b0bd9.png

Sample.Domain\Event\StockAddedToGoodsDomainEvent.cs

public class StockAddedToGoodsDomainEvent: INotification

{

public Organization Organization { get; }

public StockAddedToGoodsDomainEvent()

{

Organization = new Organization(Guid.NewGuid(), "tss","tss", DateTime.Now,null,DateTime.Now);

}

}

事件处理:StockAddedToGoodsDomainEventHandler

public class StockAddedToGoodsDomainEventHandler : INotificationHandler

{

private readonly IOrganizationRepository _iorganizationRepository;

private readonly ILoggerFactory _logger;

private readonly ISampleIntegrationEventService _sampleIntegrationEventService;

public StockAddedToGoodsDomainEventHandler(IOrganizationRepository iorganizationRepository, ILoggerFactory logger)

{

_iorganizationRepository = iorganizationRepository;

_logger = logger;

}

public async Task Handle(Domain.Events.StockAddedToGoodsDomainEvent notification, CancellationToken cancellationToken)

{

_iorganizationRepository.Add(notification.Organization);

var organization = await _iorganizationRepository.GetAsync(notification.Organization.Id);

await _iorganizationRepository.UnitOfWork.SaveEntitiesAsync();

_logger.CreateLogger(nameof(StockAddedToGoodsDomainEventHandler))

.LogTrace($"Stock with Id: {organization.Id} has been successfully Created");

}

}

资料:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值