【问题标题】:AutoMapper: Inject custom ruleset for conditional mappingAutoMapper:为条件映射注入自定义规则集
【发布时间】:2015-10-13 00:16:33
【问题描述】:

我有一个行为类 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 映射到实体(根据行为实例)。

【问题讨论】:

    标签: c# mapping automapper


    【解决方案1】:

    最后我自己做了。这个想法是使用临时创建的 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-17
      • 1970-01-01
      • 2015-10-20
      • 2020-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多