空源集合清空目标集合

时间:2017-03-27 21:55:50

标签: c# automapper

我正在合并具有List成员的对象。我告诉AutoMapper忽略空源成员但是当我合并一个带有null集合的对象时,目标get是一个空集合(即使它在地图之前有项目)。

关于如何防止这种情况的任何想法?

        ConfigurationInfo template1 = new ConfigurationInfo() {
            Columns = null //1st templates list of columns is null
        };

        ConfigurationInfo template2 = new ConfigurationInfo() {
            Columns = new List<ColumnInfo>()
        };
        template2.Columns.AddRange(existingColumns); //template2.Columns.Count == 9

        ConfigurationInfo template3 = new ConfigurationInfo() {
            Columns = null //3rd templates list of columns is null
        };

        var config = new AutoMapper.MapperConfiguration(cfg => {
            cfg.AllowNullCollections = true;
            cfg.AllowNullDestinationValues = true;

            cfg.CreateMap<ConfigurationInfo, ConfigurationInfo>()
                .ForAllMembers(option => {
                    //explicitly telling automapper to ignore null source members...
                    option.Condition((source, destination, sourceMember, destMember) => sourceMember != null);
                });

        });

        var mapper = config.CreateMapper();

        ConfigurationInfo finalTemplate = new ConfigurationInfo();

        mapper.Map(template1, finalTemplate); 
        //finalTemplate.Columns == null, which is exptected
        mapper.Map(template2, finalTemplate); 
        //finalTemplate.Columns.Count == 9, still exptected
        mapper.Map(template3, finalTemplate); 
        //finalTemplate.Columns.Count == 0, expecting 9 b/c 3rd template.Columns == null so AutoMapper should ignore. why is this happening?

4 个答案:

答案 0 :(得分:1)

我一直在努力做同样的事情。有一些配置可以解决这个问题,但它们不适用于我的情况。也许他们会为你工作。

在这种情况下,它处于全局配置中。

 Mapper.Initialize(cfg =>
{
      cfg.AllowNullCollections = true;
      cfg.AllowNullDestinationValues = true;
}

这是我在他们的回购中创建的功能请求。他们确实建议了一些可能对你有用的工作。

https://github.com/AutoMapper/AutoMapper/issues/2341

此外,对null源属性的检查不适用于值类型。您必须检查null或default。对于那部分,我创建了一个扩展名:

public static bool IsNullOrDefault(this object obj)
{
    return obj == null || (obj.GetType() is var type && type.IsValueType  && obj.Equals(Activator.CreateInstance(type)));
}

答案 1 :(得分:0)

可以覆盖IEnumerable的映射。

public class IgnoringNullValuesTypeConverter<T> : ITypeConverter<T, T> where T : class
{
    public T Convert(T source, T destination, ResolutionContext context)
    {
        return source ?? destination;
    }
}

cfg.CreateMap<IEnumerable, IEnumerable>().ConvertUsing(new IgnoringNullValuesTypeConverter<IEnumerable>());

在这种情况下它会起作用,但它不是通用解决方案。

答案 2 :(得分:0)

除了在the mapper configuration initialization中设置AllowNullCollections,您还可以选择在映射器AllowNullCollections中设置Profile,如下所示:

public class MyMapper : Profile
{
    public MyMapper()
    {
        // Null collections will be mapped to null collections.
        AllowNullCollections = true;

        CreateMap<MySource, MyDestination>();
    }
}

答案 3 :(得分:-1)

我最好的解决方案是在ExpandoObject中映射之前过滤掉null属性,然后将expando映射到目标。

        var patchTemplate = new ExpandoObject() as IDictionary<string, object>;

        foreach (var property in updatedTemplateDetails.GetType().GetProperties())
            if (property.GetValue(updatedTemplateDetails) is var propertyValue && propertyValue != null )
                patchTemplate.Add(property.Name, propertyValue);

        Mapper.Map(patchTemplate, finalTemplate);