AutoMapper:为条件映射注入自定义规则集
本文关键字:注入 自定义 规则集 映射 条件 AutoMapper | 更新日期: 2023-09-27 18:04:12
我有一个行为类TaskBehavior,它有一个单参数构造函数,它驱动表单中属性的可见性,同时属性,应该映射到数据库实体。其次,我有一个DTO类TaskDto,最后是一个数据库实体Task:
public class TaskDto
{
public string Name { get; set; }
public string Description { get; set; }
}
public class Task
{
public string Name { get; set; }
public string Description { get; set; }
}
public class TaskBehavior
{
public TaskBehavior(bool secure)
{
NameVisible = true;
DescriptionVisible = secure;
}
public bool NameVisible { get; private set; }
public bool DescriptionVisible { get; private set; }
}
我需要映射属性从taskd到任务,但只有那些,是由TaskBehavior决定的。目的是只有一个参数化规则集用于直接可见性和条件映射:
void SaveData(TaskDto taskDto)
{
var behavior = new TaskBehavior(false);
var entity = Mapper.Map<Task>(taskDto); // TODO: only map properties based on "behavior" definition
}
结果应该是在这种情况下只有Name属性从taskDto映射到实体(根据行为实例)
最后我自己让它工作。其思想是使用临时创建的MappingEngine实例和基于某些参数动态创建的映射。整个魔术在TaskMappingEngineFactory类中,它进一步将创建的MappingEngine-s缓存到静态集合以提高性能。
public static class TaskMappingEngineFactory
{
private static readonly object _lock = new object();
private static Dictionary<Enums.PortalEnum, MappingEngine> _mappingEngines = new Dictionary<Enums.PortalEnum, MappingEngine>();
public static MappingEngine GetMappingEngine(TaskBehavior taskBehavior)
{
lock (_lock)
{
MappingEngine mappingEngine;
if (!_mappingEngines.TryGetValue(taskBehavior.PortalType, out mappingEngine))
{
ConfigurationStore store = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers);
store.CreateMap<TaskInfoDetail, TaskInfoDetail>()
.ForMember(dst => dst.CanExecuteAutomatically, o => o.Condition((Func<TaskInfoDetail,bool>)(src => taskBehavior.AdvancedPropertiesVisible)))
.ForMember(dst => dst.CanExecuteManually, o => o.Condition((Func<TaskInfoDetail,bool>)(src => taskBehavior.AdvancedPropertiesVisible)));
MappingEngine engine = new MappingEngine(store);
_mappingEngines.Add(taskBehavior.PortalType, mappingEngine = engine);
}
return mappingEngine;
}
}
}
在"更新"方法中,我简单地添加了一行创建一个引擎实例工厂。很简单,很直接,不是很复杂,但现在已经足够了;)
var behavior = new TaskBehavior(NopContext.Current.PortalType());
var engine = TaskMappingEngineFactory.GetMappingEngine(behavior);
engine.Map(task, updatedTask);