首页 > 解决方案 > 如何配置 Automapper 以初始化目标中的每个成员?

问题描述

如果成员在源中不存在但在目标中存在,我们需要初始化目标成员。目前我们得到空值,除非我们手动初始化 15 个成员中的每一个:

List<string> Property = new List<string>();

这是我们的服务

    public MappingService()
    {
        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Car, Bike>();
        });

        _mapper = config.CreateMapper();
    }

    public Bike MapToBike(Car car)
    {
        return _mapper.Map<Car, Bike >(car);
    }

标签: c#automapper

解决方案


您可能不应该依赖 AutoMapper 来初始化您的集合。毕竟,将 null 作为属性值是一个有效的情况。也就是说,虽然没有标准的方法可以做到这一点,但您可以设计一些可能有效的方法。例如,如前所述,您可以使用.AfterMap()空集合填充所有空集合。这是一个扩展方法:

/// <summary>
/// Populates all properties of standard collection types with empty collections
/// </summary>
public static IMappingExpression<TSrc, TDest> InitializeNullCollectionProps<TSrc, TDest>(this IMappingExpression<TSrc, TDest> map)
{
    return map.AfterMap((src, dest) =>
    {
        var destType = typeof(TDest);

        // find all applicable properties
        var collectionProps = destType.GetProperties(BindingFlags.Public)
            .Where(propInfo =>
            {
                if (!propInfo.CanRead)
                {
                    return false;
                }

                // check if there is public setter 
                if (propInfo.GetSetMethod() == null)
                {
                    return false;
                }
                
                var propertyType = propInfo.PropertyType;
                // it can be Array, List, HashSet, ObservableCollection, etc
                var isCollection = !propertyType.IsAssignableFrom(typeof(IList));
                if (!isCollection)
                {
                    return false;
                }

                var haveParameterlessCtor =
                    propertyType.GetConstructors().Any(ctr => !ctr.GetParameters().Any());
                if (!haveParameterlessCtor)
                {
                    return false;
                }

                return true;
            })
            .ToList();
        
        // assign empty collections to applicable properties
        foreach (var propInfo in collectionProps)
        {
            var value = propInfo.GetValue(dest);
            if (value == null)
            {
                propInfo.SetValue(dest, Activator.CreateInstance(propInfo.GetType()));
            }
        }
    });
}

它的用法很简单:

Mapper.CreateMap<Src,Dest>()
   // some mappings
   .InitializeNullCollectionProps()
   // some mappings

但我不认为有一种方法可以准确地确定成员是否已经从源映射到 null,所以无论如何它都会有空的集合值。


推荐阅读