abp.io领域层无Clock.Now静态类,如何在DDD模式下使用IClock服务能力
在ABP.io领域层使用IClock的三种实现方案
方案1:时间参数从上层传入(最优推荐)
聚合根本身不需要依赖任何外部服务,将当前时间作为方法入参传入,保持聚合根的纯域模型属性,也更方便单元测试。
修改后的聚合根代码示例:
public class Event : FullAuditedAggregateRoot<Guid> { public string Title { get; set; } public string Description { get; set; } public bool IsFree { get; set; } public DateTime StartTime { get; set; } public DateTime BookingTime { get; set; } public ICollection<EventAttendee> Attendees { get; set; } public void AddAttendee(Guid attendeeId, DateTime currentTime) { if (currentTime < BookingTime) { throw new BusinessException( "Error.EventClosed", $"您无法在{BookingTime}之前预定该活动。"); } var attendee = new EventAttendee { UserId = attendeeId }; Attendees.Add(attendee); } public Event() { Attendees = new List<EventAttendee>(); } }
上层应用层调用时,注入IClock服务,将IClock.Now作为参数传入方法即可。
方案2:逻辑抽取到领域服务
如果时间相关的领域规则比较复杂,或者需要在多个地方复用,可以将相关逻辑抽到领域服务中,在领域服务中注入IClock:
public class EventManager : DomainService { private readonly IClock _clock; // ABP依赖注入会自动注入IClock实例 public EventManager(IClock clock) { _clock = clock; } public void AddAttendee(Event @event, Guid attendeeId) { if (_clock.Now < @event.BookingTime) { throw new BusinessException( "Error.EventClosed", $"您无法在{@event.BookingTime}之前预定该活动。"); } @event.Attendees.Add(new EventAttendee { UserId = attendeeId }); } }
应用层直接注入EventManager调用对应方法即可,不需要自己处理IClock的注入逻辑。
方案3:静态兼容方案(仅推荐快速迁移旧代码使用)
如果是老项目迁移不想改动太多现有逻辑,可以直接使用ABP框架提供的静态Clock类,虽然官方推荐用注入的IClock,但静态Clock实际上还是保留了兼容入口,用法和aspnet.boilerplate完全一致:
if (Clock.Now < BookingTime) { // 原有逻辑不变 }
注意该方式不利于单元测试,仅建议临时过渡使用。
内容的提问来源于stack exchange,提问作者Gianpiero
相关产品推荐
相关产品推荐

