Использование 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);