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映射到实体(根据行为实例)

AutoMapper:为条件映射注入自定义规则集

最后我自己让它工作。其思想是使用临时创建的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);