web-dev-qa-db-fra.com

Automapper - comment mapper les paramètres du constructeur à la place des paramètres de propriété

Dans les cas où mes paramètres de destination sont privés, il peut être utile de mapper cet objet à l'aide du constructeur de l'objet de destination. Comment feriez-vous cela en utilisant Automapper?

90
jlembke

Utilisez ConstructUsing

cela vous permettra de spécifier le constructeur à utiliser lors du mappage. mais alors toutes les autres propriétés seront automatiquement mappées selon les conventions.

Notez également que ceci diffère de ConvertUsing en ce que convertir en utilisant ne continuera pas à mapper via les conventions, il vous donnera plutôt le contrôle total du mappage.

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; }
    }
}
130
Jon Erickson

Vous devez utiliser la méthode Map qui vous permet de définir la destination. Par exemple :

Mapper.CreateMap<ObjectFrom, ObjectTo>()

var from = new ObjectFrom { Name = "Jon", Age = 25 };

var to = Mapper.Map(from, new ObjectTo(param1));
9
Matthieu

La meilleure pratique consiste à utiliser les approches documentées d'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)));
5
Anton Shcherbyna

Au moment de la rédaction de cette réponse, AutoMapper le fera automatiquement (avec un simple appel CreateMap<>()) si les propriétés correspondent aux paramètres du constructeur. Bien sûr, si les choses ne concordent pas, utiliser .ConstructUsing(...) est la solution.

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>();
    }
}

Remarque: Cela suppose que vous utilisez Profiles pour configurer vos mappages d’applicateur automatique.

Utilisé comme ci-dessous, cela produit le bon objet:

var model = new PersonModel
{
    Id = 1
    Name = "John Smith"
}

// will correctly call the (id, name) constructor of Person
_mapper.Map<Person>(model);

Vous pouvez en savoir plus sur la construction d’un automappeur dans le répertoire officiel wiki sur GitHub

0
lxalln