Automapper - как сопоставить параметры конструктора вместо установщиков свойств
в случаях, когда мои целевые сеттеры являются частными, я могу захотеть сопоставить объект с помощью конструктора целевого объекта. Как бы вы сделали это с помощью Automapper?
4 ответа:
использовать
ConstructUsing
это позволит вам указать, какой конструктор использовать в течение сопоставления. но тогда все остальные свойства будут автоматически сопоставлены в соответствии с соглашениями.
Также обратите внимание, что это отличается от
ConvertUsing
в этом преобразовании использование не будет продолжать отображаться через соглашения, вместо этого он даст вам полный контроль над отображением.Mapper.CreateMap<ObjectFrom, ObjectTo>() .ConstructUsing(x => new ObjectTo(arg0, arg1, etc));
...
using AutoMapper; using NUnit.Framework; namespace UnitTests { [TestFixture] public class Tester { [Test] public void Test_ConstructUsing() { Mapper.CreateMap<ObjectFrom, ObjectTo>() .ConstructUsing(x => new ObjectTo(x.Name)); var from = new ObjectFrom { Name = "Jon", Age = 25 }; ObjectTo to = Mapper.Map<ObjectFrom, ObjectTo>(from); Assert.That(to.Name, Is.EqualTo(from.Name)); Assert.That(to.Age, Is.EqualTo(from.Age)); } } public class ObjectFrom { public string Name { get; set; } public int Age { get; set; } } public class ObjectTo { private readonly string _name; public ObjectTo(string name) { _name = name; } public string Name { get { return _name; } } public int Age { get; set; } } }
вы должны использовать
Map
метод, который позволяет установить назначение. Например :Mapper.CreateMap<ObjectFrom, ObjectTo>() var from = new ObjectFrom { Name = "Jon", Age = 25 }; var to = Mapper.Map(from, new ObjectTo(param1));
рекомендуется использовать документированные подходы из AutoMapper https://github.com/AutoMapper/AutoMapper/wiki/Construction
public class SourceDto { public SourceDto(int valueParamSomeOtherName) { Value = valueParamSomeOtherName; } public int Value { get; } } Mapper.Initialize(cfg => cfg.CreateMap<Source, SourceDto>().ForCtorParam("valueParamSomeOtherName", opt => opt.MapFrom(src => src.Value)));
на момент написания этого ответа AutoMapper сделает это автоматически (с помощью простого
CreateMap<>()
вызов) для вас, если свойства соответствуют параметрам конструктора. Конечно, если вещи не совпадают, то с помощью.ConstructUsing(...)
- это путь.public class PersonViewModel { public int Id { get; set; } public string Name { get; set; } } public class Person { public Person (int id, string name) { Id = id; Name = name; } public int Id { get; } public string Name { get; } } public class PersonProfile : Profile { public PersonProfile() { CreateMap<PersonProfile, Person>(); } }
Примечание: это предполагает, что вы используете профили для настройки сопоставлений automapper.
при использовании, как показано ниже, это дает правильный объект:
var model = new PersonModel { Id = 1 Name = "John Smith" } // will correctly call the (id, name) constructor of Person _mapper.Map<Person>(model);
вы можете прочитать больше о конструкция automapper в официальном wiki на GitHub