web-dev-qa-db-ja.com

Automapper-プロパティセッターの代わりにコンストラクターパラメーターにマップする方法

宛先セッターがプライベートの場合、宛先オブジェクトのコンストラクターを使用してオブジェクトにマップすることができます。 Automapperを使用してこれをどのように行いますか?

97
jlembke

ConstructUsingを使用

これにより、マッピング中に使用するコンストラクターを指定できます。ただし、その他のプロパティはすべて、規則に従って自動的にマッピングされます。

また、これはConvertUsingとは異なることに注意してください。それは、convert usingが規則を介してマッピングを続行せず、代わりにマッピングの完全な制御を提供するという点です。

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

宛先を設定できるMapメソッドを使用する必要があります。例えば ​​:

Mapper.CreateMap<ObjectFrom, ObjectTo>()

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

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

ベストプラクティスは、AutoMapperから文書化されたアプローチを使用することです http://docs.automapper.org/en/stable/Construction.html

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)));
8

この回答を書いている時点で、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<PersonViewModel, Person>();
    }
}

注:これは、オートマッパーマッピングをセットアップするために Profiles を使用していることを前提としています。

以下のように使用すると、これにより正しいオブジェクトが生成されます。

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

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

オートマッパーの構築について詳しくは、公式の wiki on GitHub をご覧ください。

1
lxalln