web-dev-qa-db-ja.com

Automapper:プロパティを手動でマップする

Automapperを使用してDTO <-> Entitiesをマッピングし始めましたが、うまく機能しているようです。

一部の特殊なケースでは、一部のプロパティのみをマップし、追加のチェックを実行します。自動マッパーがない場合、コードは次のようになります(fasterflectのPropertyExtensionsを使用)。

_object target;
object source;
string[] changedPropertyNames = { };

foreach (var changedPropertyName in changedPropertyNames)
{
    var newValue = source.GetPropertyValue(changedPropertyName);
    target.SetPropertyValue(changedPropertyName, newValue);
}
_

もちろん、型変換が必要な場合、このコードは機能しません。 Automapperは組み込みのTypeConverterを使用し、特定のTypeConverter実装もいくつか作成しました。

今、私は個々のプロパティをマップし、オートマッパーのタイプ変換実装を使用することが可能かどうか疑問に思っています、このようなもの

_Mapper.Map(source, target, changedPropertyName);
_

更新

もっと情報が必要だと思います:

私はすでにいくつかのマップを作成しました。

_Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
_

また、CalendarEventのnull可能なdateTimeプロパティのカスタムタイプコンバーターを使用してマップを作成しました。

_Mapper.CreateMap<DateTimeOffset?, DateTime?>().ConvertUsing<NullableDateTimeOffsetConverter>();
_

私はこれらのマップをWeb API ODataコントローラーで使用します。新しいEntityDTOを投稿するときは、

_Mapper.Map(entityDto, entity);
_

エンティティをデータストアに保存します。

しかし、PATCHを使用する場合、_Delta<TDto> entityDto_がコントローラーメソッドに渡されます。したがって、entityDto.GetChangedPropertyNames()を呼び出して、変更された値で既存の永続エンティティを更新する必要があります。

基本的にこれは私の簡単な解決策で機能していますが、変更されたプロパティの1つがDateTimeOffsetNullableDateTimeOffsetConverterを使用します。

13
krombi

以下のようにする必要があるよりも、いくつかの選択したプロパティのみをマップしたい場合

// Create a map
var map = CreateMap<Source,Target>();
// ingnore all existing binding of property
map.ForAllMembers(opt => opt.Ignore());
// than map property as following
map.ForMember(dest => dest.prop1, opt => opt.MapFrom( src => src.prop1));
map.ForMember(dest => dest.prop2, opt => opt.MapFrom( src => src.prop2));
24
Pranay Rana

MapFromメソッドを使用して投影を作成できます- http://automapper.readthedocs.io/en/latest/Projection.html =

Mapper.Map(source, target)
   .ForMember(m => m.Property, opt => opt.MapFrom(src => src.ChangedProperty));

たとえば(AutoMapperのドキュメントを参照):

// Model
var calendarEvent = new CalendarEvent
    {
        Date = new DateTime(2008, 12, 15, 20, 30, 0),
        Title = "Company Holiday Party"
    };

// Configure AutoMapper
Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
    .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.Date.Date))
    .ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.Date.Hour))
    .ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.Date.Minute));
11
Pawel Maga

質問を正しく読んだ場合は、宛先(ターゲット)プロパティがコンバージョンに一致する限り、はい。

つまり、stringからboolStatus"A"または"I"(アクティブ/非アクティブ)、私は次のようなことができます:

.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status == "A"))

そして、他の方向に行くとき、それを元に戻します:

.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status ? "A" : "I"))

日付の例:

.ForMember(dest => dest.SomeDate, opt => opt.MapFrom(src => src.SomeDate.ToString("M/d/yyyy")));
1
Mark C.