Automapper AfterMap异常行为:Manager聚合根事件未触发
问题分析
你的问题出在Automapper的AfterMap用法上:AfterMap中的dest是值传递的参数,你在AfterMap里重新给dest赋值new ManagerAggregateRoot(...),只会修改局部变量,并不会替换Automapper最初创建的那个聚合根实例。而你直接new的时候,正确触发了聚合根构造函数里的事件逻辑,但Automapper最终返回的还是它自己初始化的空实例(或默认构造的实例),自然没有事件。
至于UserAggregateRoot看似正常,大概率是巧合——要么你的UserAggregateRoot默认构造函数也会触发UserCreatedEvent,要么测试逻辑存在疏漏,实际上它的映射也存在同样的隐患。
解决方案
不要用AfterMap重新创建聚合根实例,改用Automapper的ConstructUsing方法,它的作用就是指定如何创建目标类型的实例,完全匹配你通过命令构造聚合根的场景:
修改Manager的映射配置
CreateMap<ManagerRegisterCommand, ManagerAggregateRoot>() .ConstructUsing((src, context) => { var managerId = context.Mapper.Map<ManagerId>(src.Id); var email = context.Mapper.Map<Email>(src.ManagerEmail); return new ManagerAggregateRoot(managerId, email); });
同步修正User的映射配置(消除潜在问题)
CreateMap<UserRegisterCommand, UserAggregateRoot>() .ConstructUsing((src, context) => { var userId = context.Mapper.Map<UserId>(src.Id); var name = context.Mapper.Map<Name>(src.Name); var login = context.Mapper.Map<Email>(src.Login); var password = context.Mapper.Map<Password>(src.Password); var birthDate = context.Mapper.Map<BirthDate>(src.BirthDate); return new UserAggregateRoot(userId, login, password, name, birthDate); });
原理说明
ConstructUsing会让Automapper跳过默认的实例化逻辑,直接使用你提供的委托创建目标对象,这样返回的就是你通过构造函数创建的、已正确触发事件的聚合根实例。AfterMap的设计初衷是在已完成映射的实例上做额外修改,比如补充属性、调用实例方法,而非替换整个实例。
修改后,无论是User还是Manager的聚合根,通过Automapper映射出的实例都会正确包含构造函数中触发的领域事件。
内容的提问来源于stack exchange,提问作者PelikanFix16
相关产品推荐
相关产品推荐

