如何使用 automapper 和 constructUsing 映射一个有点复杂的架构
How to map a somewhat complex architecture with automapper and constructUsing
我有以下情况无法正确映射:
我从对 camunda 的调用中收到了以下对象的列表 api。
public class CamundaTask
{
public string FormKey { get; set; }
public string Id { get; set; }
public string Name { get; set; }
...
}
我想根据 formkey 将其映射到我的代码中的特定任务(ContactUpdateTask
或 OrganisationAquisitionTask
)。
以下是我的架构:
public class BaseTask
{
public virtual string TaskType { get; set; }
public string Id { get; set; }
public int Priority { get; set; }
public string Key { get; set; }
...
}
public abstract class ProcessTask<TContext> : BaseTask
{
public TContext TaskContext { get; set; }
}
public class ContactUpdateContext
{
public Guid PersonId { get; set; }
public string FullName { get; set; }
}
public class OrganisationAquisitionContext
{
public Guid OrganisationId { get; set; }
public string Name { get; set; }
}
public class ContactUpdateTask : ProcessTask<ContactUpdateContext>
{
public override string TaskType { get => "UpdateContact"; }
}
public class OrganisationAquisitionTask : ProcessTask<OrganisationAquisitionContext>
{
public override string TaskType { get => "OrganisationAquisition"; }
}
我知道如何处理简单的继承和自动映射器,但整个 TContext 让我有点失望。
这是我到目前为止所拥有的,但它会产生以下错误:"Mapper not initialized. Call Initialize with appropriate configuration."
CreateMap<ContactUpdateTask, ProcessTask<ContactUpdateContext>>().ReverseMap();
CreateMap<ContactValidationTask, ProcessTask<OrganisationAquisitionTask>>().ReverseMap();
CreateMap<OrganisationAquisitionTask, ProcessTask<ContactValidationTask>>().ReverseMap();
CreateMap<BaseTask, CamundaTask>()
.ForMember(t => t.FormKey, opt => opt.MapFrom(p => p.TaskType))
.ForMember(t => t.Assignee, opt => opt.MapFrom(p => p.Owner))
.ForMember(t => t.Id, opt => opt.MapFrom(p => p.Key))
.ForAllOtherMembers(opt => opt.Ignore());
CreateMap<CamundaTask, ContactUpdateTask>()
.ForMember(t => t.TaskType, opt => opt.MapFrom(p => p.FormKey))
.ForMember(t => t.Owner, opt => opt.MapFrom(p => p.Assignee))
.ForMember(t => t.Key, opt => opt.MapFrom(p => p.Id))
.ForAllOtherMembers(opt => opt.Ignore());
CreateMap<CamundaTask, ContactValidationTask>()
.ForMember(t => t.TaskType, opt => opt.MapFrom(p => p.FormKey))
.ForMember(t => t.Owner, opt => opt.MapFrom(p => p.Assignee))
.ForMember(t => t.Key, opt => opt.MapFrom(p => p.Id))
.ForAllOtherMembers(opt => opt.Ignore());
CreateMap<CamundaTask, OrganisationAquisitionTask>()
.ForMember(t => t.TaskType, opt => opt.MapFrom(p => p.FormKey))
.ForMember(t => t.Owner, opt => opt.MapFrom(p => p.Assignee))
.ForMember(t => t.Key, opt => opt.MapFrom(p => p.Id))
.ForAllOtherMembers(opt => opt.Ignore());
CreateMap<CamundaTask, BaseTask>()
.ConstructUsing((CamundaTask task) =>
{
switch (task.FormKey.ToLower())
{
case "updateorganization":
return Mapper.Map<ContactUpdateTask>(task);
case "contactValidation":
return Mapper.Map<ContactValidationTask>(task);
case "organizationacquisition":
return Mapper.Map<OrganisationAquisitionTask>(task);
}
return Mapper.Map<BaseTask>(task);
})
.ForMember(t => t.TaskType, opt => opt.MapFrom(p => p.FormKey))
.ForMember(t => t.Owner, opt => opt.MapFrom(p => p.Assignee))
.ForMember(t => t.Key, opt => opt.MapFrom(p => p.Id))
.ForAllOtherMembers(opt => opt.Ignore());
我用下面一行代码映射:
var tasks = _mapper.Map<IEnumerable<BaseTask>>(camundaTasks)
其中 camundaTasks
的类型为 IEnumerable<CamundaTask>
执行映射的正确方法是什么,以便我的任务列表包含 ContactUpdateTask
或 OrganisationAquisitionTask
的对象,具体取决于 CamundaTask
的 formkey?
所以这里发生的是你以 non-static 方式初始化 Automapper(从你原来的 post 中不清楚,但我可以推断出这一点,因为我的评论似乎已经解决了你的问题),但您在 ConstructUsing 方法中静态使用 Automapper。
有两种解决方法:
1) 静态使用Automapper
Mapper.Initialize(cfg=> cfg.CreateMap<CamundaTask, BaseTask>());
2) 使用 ResolutionContext
.ConstructUsing((CamundaTask task, ResolutionContext context) =>
{
switch (task.FormKey.ToLower())
{
case "updateorganization":
return context.Mapper.Map<ContactUpdateTask>(task);
case "contactValidation":
return context.Mapper.Map<ContactValidationTask>(task);
case "organizationacquisition":
return context.Mapper.Map<OrganisationAquisitionTask>(task);
}
return context.Mapper.Map<BaseTask>(task);
})
我有以下情况无法正确映射:
我从对 camunda 的调用中收到了以下对象的列表 api。
public class CamundaTask
{
public string FormKey { get; set; }
public string Id { get; set; }
public string Name { get; set; }
...
}
我想根据 formkey 将其映射到我的代码中的特定任务(ContactUpdateTask
或 OrganisationAquisitionTask
)。
以下是我的架构:
public class BaseTask
{
public virtual string TaskType { get; set; }
public string Id { get; set; }
public int Priority { get; set; }
public string Key { get; set; }
...
}
public abstract class ProcessTask<TContext> : BaseTask
{
public TContext TaskContext { get; set; }
}
public class ContactUpdateContext
{
public Guid PersonId { get; set; }
public string FullName { get; set; }
}
public class OrganisationAquisitionContext
{
public Guid OrganisationId { get; set; }
public string Name { get; set; }
}
public class ContactUpdateTask : ProcessTask<ContactUpdateContext>
{
public override string TaskType { get => "UpdateContact"; }
}
public class OrganisationAquisitionTask : ProcessTask<OrganisationAquisitionContext>
{
public override string TaskType { get => "OrganisationAquisition"; }
}
我知道如何处理简单的继承和自动映射器,但整个 TContext 让我有点失望。 这是我到目前为止所拥有的,但它会产生以下错误:"Mapper not initialized. Call Initialize with appropriate configuration."
CreateMap<ContactUpdateTask, ProcessTask<ContactUpdateContext>>().ReverseMap();
CreateMap<ContactValidationTask, ProcessTask<OrganisationAquisitionTask>>().ReverseMap();
CreateMap<OrganisationAquisitionTask, ProcessTask<ContactValidationTask>>().ReverseMap();
CreateMap<BaseTask, CamundaTask>()
.ForMember(t => t.FormKey, opt => opt.MapFrom(p => p.TaskType))
.ForMember(t => t.Assignee, opt => opt.MapFrom(p => p.Owner))
.ForMember(t => t.Id, opt => opt.MapFrom(p => p.Key))
.ForAllOtherMembers(opt => opt.Ignore());
CreateMap<CamundaTask, ContactUpdateTask>()
.ForMember(t => t.TaskType, opt => opt.MapFrom(p => p.FormKey))
.ForMember(t => t.Owner, opt => opt.MapFrom(p => p.Assignee))
.ForMember(t => t.Key, opt => opt.MapFrom(p => p.Id))
.ForAllOtherMembers(opt => opt.Ignore());
CreateMap<CamundaTask, ContactValidationTask>()
.ForMember(t => t.TaskType, opt => opt.MapFrom(p => p.FormKey))
.ForMember(t => t.Owner, opt => opt.MapFrom(p => p.Assignee))
.ForMember(t => t.Key, opt => opt.MapFrom(p => p.Id))
.ForAllOtherMembers(opt => opt.Ignore());
CreateMap<CamundaTask, OrganisationAquisitionTask>()
.ForMember(t => t.TaskType, opt => opt.MapFrom(p => p.FormKey))
.ForMember(t => t.Owner, opt => opt.MapFrom(p => p.Assignee))
.ForMember(t => t.Key, opt => opt.MapFrom(p => p.Id))
.ForAllOtherMembers(opt => opt.Ignore());
CreateMap<CamundaTask, BaseTask>()
.ConstructUsing((CamundaTask task) =>
{
switch (task.FormKey.ToLower())
{
case "updateorganization":
return Mapper.Map<ContactUpdateTask>(task);
case "contactValidation":
return Mapper.Map<ContactValidationTask>(task);
case "organizationacquisition":
return Mapper.Map<OrganisationAquisitionTask>(task);
}
return Mapper.Map<BaseTask>(task);
})
.ForMember(t => t.TaskType, opt => opt.MapFrom(p => p.FormKey))
.ForMember(t => t.Owner, opt => opt.MapFrom(p => p.Assignee))
.ForMember(t => t.Key, opt => opt.MapFrom(p => p.Id))
.ForAllOtherMembers(opt => opt.Ignore());
我用下面一行代码映射:
var tasks = _mapper.Map<IEnumerable<BaseTask>>(camundaTasks)
其中 camundaTasks
的类型为 IEnumerable<CamundaTask>
执行映射的正确方法是什么,以便我的任务列表包含 ContactUpdateTask
或 OrganisationAquisitionTask
的对象,具体取决于 CamundaTask
的 formkey?
所以这里发生的是你以 non-static 方式初始化 Automapper(从你原来的 post 中不清楚,但我可以推断出这一点,因为我的评论似乎已经解决了你的问题),但您在 ConstructUsing 方法中静态使用 Automapper。
有两种解决方法:
1) 静态使用Automapper
Mapper.Initialize(cfg=> cfg.CreateMap<CamundaTask, BaseTask>());
2) 使用 ResolutionContext
.ConstructUsing((CamundaTask task, ResolutionContext context) =>
{
switch (task.FormKey.ToLower())
{
case "updateorganization":
return context.Mapper.Map<ContactUpdateTask>(task);
case "contactValidation":
return context.Mapper.Map<ContactValidationTask>(task);
case "organizationacquisition":
return context.Mapper.Map<OrganisationAquisitionTask>(task);
}
return context.Mapper.Map<BaseTask>(task);
})