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

时间:2015-07-22 21:56:01

标签: c# mapping automapper

我有一个行为类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; }
}

我需要将TaskDto中的属性映射到Task,但只需要由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映射到实体(根据行为实例)。

1 个答案:

答案 0 :(得分:0)

最后我让它自己工作了。我们的想法是使用ad-hoc创建的MappingEngine实例和基于SOME参数的动态创建的映射。整个魔术在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);