宛先セッターがプライベートの場合、宛先オブジェクトのコンストラクターを使用してオブジェクトにマップすることができます。 Automapperを使用してこれをどのように行いますか?
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; }
}
}
宛先を設定できるMap
メソッドを使用する必要があります。例えば :
Mapper.CreateMap<ObjectFrom, ObjectTo>()
var from = new ObjectFrom { Name = "Jon", Age = 25 };
var to = Mapper.Map(from, new ObjectTo(param1));
ベストプラクティスは、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)));
この回答を書いている時点で、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 をご覧ください。