Использование AutoMapper для объединения объектов

Я пытаюсь использовать AutoMapper для объединения данных из нескольких объектов, и я столкнулся с парой проблем, которые я не могу решить.

У меня есть объект, как:

public class Parent
{
    public string Id { get; set; }
    public List<Child> Children { get; set; }
}
public class Child
{
    public string Key { get; set; }
    public int? Value1 { get; set; }
    public int? Value2 { get; set; }
    public int? Value3 { get; set; }
    public int? Value4 { get; set; }
    public int? Value5 { get; set; }
}

Очевидно, что дочерние свойства не являются целыми числами, но большинство из них имеют значение null.

У меня есть эти объекты на двух разных уровнях моего приложения, поэтому я использую AutoMapper для преобразования между ними:

{
    Mapper.CreateMap<Parent, ParentDTO>();
    Mapper.CreateMap<ParentDTO, Parent>();

    Mapper.CreateMap<Child, ChildDTO>();
    Mapper.CreateMap<ChildDTO, Child>();
}

Преобразование работает хорошо, и я доволен тем, что оно делает. Однако теперь мне нужно объединить несколько объектов одного типа. У меня будет одна копия объекта, у которого заполнено большинство или все свойства, и другая копия, у которой есть только несколько, а остальные будут нулевыми. Я хочу, чтобы любые ненулевые свойства второго (частичного) объекта были сопоставлены с соответствующим полем в первом (уже заполненном) объекте. Поскольку принятый ответ на этот ответ гласит, я должен быть в состоянии использовать AutoMapper, чтобы сделать это, но он не дает никаких четких примеров.

Однако, когда я иду на выполнение операции, я получаю объект, который идентичен любому из объектов, а не объединен, как я хочу.

{
    var bigParent = new Parent
    {
        Id = "14",
        Children = new List<Child>
        {
            new Child
            {
                Key = "A",
                Value1 = 10,
                Value2 = 20,
                Value3 = 30,
                Value4 = 40,
                Value5 = 50
            }                   
        }
    };

    var merge = new Parent
    {
        Id = "14",
        Children = new List<Child>
        {
            new Child
            {
                Key = "A",
                Value1 = null,
                Value2 = null,
                Value3 = 100,
                Value4 = null,
                Value5 = null
            }
        }
    };

    var res = Mapper.Map(merge, bigParent);
}

Я ожидаю, что Child будет иметь значения 10, 20, 100, 40 и 50. Однако, в зависимости от того, добавлю ли я слияние в качестве источника или места назначения в Mapper.Map, я получаю либо ноль, ноль, 100, нуль, ноль или 10, 20 30, 40, 50.

Есть ли способ получить ожидаемые значения? Я думаю, что наличие списка - это то, что вызывает проблемы, так как он не знает, как выстроить сущности (чтобы определить, являются ли они одинаковыми или нет). Если ответ на любые вопросы, я смог бы определить, являются ли дочерние записи одинаковыми, увидев, являются ли одно или несколько свойств одинаковыми (в этом примере, Key).

2 ответа

Если вы хотите игнорировать нулевые значения в отображениях, определенных в профиле AutoMapper, используйте:

public class MappingProfile : AutoMapper.Profile
{
  public MappingProfile()
  {
     this.CreateMap<Parent, Parent>()
         .ForAllMembers(o => o.Condition((source, destination, member) => member != null));
  }
}

Automapper способен на это, ваш маппер должен быть настроен так:

Mapper.Initialize(cfg =>
{
    // necessary if you are mapping parent to a parent
    cfg.CreateMap<Parent, Parent>()
        .ForAllMembers(options =>
        {
            options.Condition(src => src.DestinationValue == null);
        });
    // necessary if you are mapping your child to a child
    cfg.CreateMap<Child, Child>()
        .ForAllMembers(options =>
        {
            options.Condition(src => src.DestinationValue == null);
        });
});

И тогда ваше использование как таковое:

var bigParent = new Parent
{
    Id = "14",
    Children = new List<Child>
    {
        new Child
        {
            Key = "A",
            Value1 = 10,
            Value2 = 20,
            Value3 = 30,
            Value4 = 40,
            Value5 = 50
        }
    }
};

var merge = new Parent
{
    Id = "14",
    Children = new List<Child>
    {
        new Child
        {
            Key = "A",
            Value1 = null,
            Value2 = null,
            Value3 = 100,
            Value4 = null,
            Value5 = null
        }
    }
};

var bigChild = new Child
{
    Key = "A",
    Value1 = 10,
    Value2 = 20,
    Value3 = 30,
    Value4 = 40,
    Value5 = 50
};

var mergeChild = new Child
{
    Key = "A",
    Value1 = null,
    Value2 = null,
    Value3 = 100,
    Value4 = null,
    Value5 = null
};

Mapper.Map(bigChild, mergeChild);
Debug.Assert(mergeChild.Value3 == 100);

Mapper.Map(bigParent, merge);
Debug.Assert(merge.Children[0].Value3 == 100);
Другие вопросы по тегам