【问题标题】:Specifying AutoMapper mappings based on list of properties根据属性列表指定 AutoMapper 映射
【发布时间】:2018-07-31 08:50:06
【问题描述】:

各位大侠们好,

我不确定这是否可能,或者我正在与风车作斗争,但我想要完成的是一种基于 AutoMapper 的通用映射器。

使用此映射器,我将能够指定要映射的某些类型,并且源类型和目标类型将是相同的。

然后我想提供一个属性列表作为方法的参数,该方法将指定特定类型的所有属性的子集。

所以调用方法看起来像这样:

给定以下方法签名

public T Map<TProp>(T source1, T source2, params Expression<Func<T,TProp>>[] propsToMap)

amm 代表 AutoModelMapper。

amm.Map<>(
        adminFeeSource,
        adminFeeDestination,
        fee => fee.FeeAmount,
        fee => fee.NoValueMessage);

如何以安全的方式实现这一点(使用泛型)?这可能吗?

亲切的问候

【问题讨论】:

    标签: c# generics automapper


    【解决方案1】:

    我不明白您的问题 TBH,因为 AFAIK 您需要为 AutoMapper 注册映射才能根据其文档工作,但看看这是否会对您有所帮助。

    使用静态Mapper

    public class MapperConfig
    {
        public static MapperConfiguration MapperCfg { get; private set; }
        public static IMapper Mapper { get; private set; }
    
        public static void RegisterMappings()
        {
            MapperCfg = new MapperConfiguration(cfg =>
            {
                cfg.AllowNullCollections = true;
                cfg.AllowNullDestinationValues = true;
    
                #region Entity VMs
    
                cfg.CreateMap<Address, AddressVM>().MaxDepth(3).ReverseMap();
                cfg.CreateMap<ApplicationUserConfig, ApplicationUserConfigVM>().MaxDepth(3).ReverseMap();
                // ... You need to define the objects in the mapper config
                cfg.CreateMap<WarehouseConfig, WarehouseConfigVM>().MaxDepth(3).ReverseMap();
    
                #endregion
            });
    
            Mapper = MapperCfg.CreateMapper();
        }
    }
    

    在您的应用程序启动时调用MapperConfig.RegisterMappings(); 以注册模型映射。

    然后你可以创建一个扩展

    public static class Extension
    {
        public static IPagedList<TDestination> ToMappedPagedList<TSource, TDestination>(this IPagedList<TSource> list)
        {
            IMapper mapper = MapperConfig.Mapper;
    
            IEnumerable<TDestination> sourceList = mapper.Map<IEnumerable<TDestination>>(list);
            IPagedList<TDestination> pagedResult = new StaticPagedList<TDestination>(sourceList, list.GetMetaData());
    
            return pagedResult;
        }
    
        public static IEnumerable<TDestination> Map<TSource, TDestination>(this IEnumerable<TSource> list)
            where TSource : class
            where TDestination : class, new()
        {
            IMapper mapper = MapperConfig.Mapper;
    
            IEnumerable<TDestination> sourceList = mapper.Map<IEnumerable<TDestination>>(list);
    
            return sourceList;
        }
    
        public static TDestination Map<TSource, TDestination>(this TSource entity)
            where TSource : class
            where TDestination : class, new()
        {
            IMapper mapper = MapperConfig.Mapper;
    
            return mapper.Map<TDestination>(entity);
        }
    }
    

    理想情况下,您应该在 IoC 容器中注册您的 IMapper,而不是直接在您的 Extention.cs 中调用 MapperConfig.Mapper,但这将适用于示例。

    用法:

    Address address = new Address();
    AddressVM = address.Map<Address, AddressVM>();
    

    【讨论】:

    • 当然你必须注册,但我想让它在某种意义上是动态的。因此,假设我有一些类型 T,以及该类型的属性子集。现在我想要实现的是创建通用方法,该方法将基于参数创建和注册该映射,因此 .. cfg.CreateMap() 用于该列表中的所有属性。所以我正在寻找类似 cfg.Create().ForMembers(List) 的东西。希望现在更清楚了。
    • @kamilw 你试过Dynamic and Expando Objects Mapping吗?您的示例方法签名似乎想要映射相同类型的两个对象,同时允许您指定哪个属性去哪个。如果 source1 和 source2 真的属于同一类型,这似乎特别令人困惑和毫无意义。
    猜你喜欢
    • 1970-01-01
    • 2019-04-12
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 2019-03-30
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多