55

ResolveUsingIValueResolverを使用するオーバーロードを無視し、次の2つのメソッドのみを確​​認します。

void ResolveUsing(Func<TSource, object> resolver);
void MapFrom<TMember>(Expression<Func<TSource, TMember>> sourceMember);

これら2つの主な違いは、MapFromがをとるのに対し、をとるということResolveUsingです。Func<TSource, object>Expression<Func<TSource, TMember>>

ただし、ラムダ式でこれらのメソッドの1つを実際に使用するクライアントコードでは、これらは交換可能であるように見えます。

Mapper.CreateMap<SourceType, DestType>() // uses ResolveUsing
   .ForMember(d => d.DestPropX, o => o.ResolveUsing(s => s.SourcePropY));

Mapper.CreateMap<SourceType, DestType>() // uses MapFrom
   .ForMember(d => d.DestPropX, o => o.MapFrom(s => s.SourcePropY));

では、最終的に上記の2つの選択肢の違いは何ですか?一方はもう一方よりも速いですか?一方が他方よりも良い選択であり、もしそうなら、いつ/なぜですか?

4

5 に答える 5

70

過去に、私はAutomapperの作者とメーリングリストで長いメール交換をしました。MapFromは、式全体でnullチェックを実行します。

したがって、これを行うことができopt => opt.MapFrom(src => src.SomeProp.Way.Down.Here.Somewhere)、各レベルでnullがチェックされます(フラット化の場合と同様)。

于 2013-02-15T00:08:11.797 に答える
22

新しいC#6null条件演算子を使用していくつかのベンチマークを実行しました ?.

次のシナリオを考えてみましょう。クラスAには子クラスBがあり、その子には子Cがあり、そのNameプロパティをDTOにフラット化する必要があります。私は2つのバリアントをテストしました:

// using mapfrom
CreateMap<MapFromA, MapFromADto>()
    .ForMember(dto => dto.Name, o => o.MapFrom(a => a.B.C.Name));

// using resolveusing with elvis
CreateMap<ResolveUsingX, ResolveUsingXDto>()
    .ForMember(dto => dto.Name, o => o.ResolveUsing(x => x.Y?.Z?.Name));

私は_mapper.Map<ResolveUsingXDto>(x);または_mapper.Map<MapFromADto>(a);1000の異なる電話ResolveUsingX xをかけMapFromA a、を使用して時間をかけましたSystem.Diagnostics.StopWatch。これが私の結果です:

Distinct elements per batch: 1000; # batches for average: 25

A->B->C.Name, C is never null.
MapForm - average time taken for 1000x: 5527,84 ticks = 1,44 ms.
ResolveUsing - average time taken for 1000x: 5479,76 ticks =  1,4 ms.

A->B->C.Name, C is null 1/3 of the time.
MapForm - average time taken for 1000x: 72924,4 ticks = 27,44 ms.
ResolveUsing - average time taken for 1000x: 5351,2 ticks =  1,48 ms.

A->B->C.Name, C is null 1/2 of the time.
MapForm - average time taken for 1000x: 107016,92 ticks = 40,52 ms.
ResolveUsing - average time taken for 1000x: 5835,32 ticks =  1,56 ms.

A->B->C.Name, C is null 2/3 of the time.
MapForm - average time taken for 1000x: 141437,96 ticks = 53,64 ms.
ResolveUsing - average time taken for 1000x: 5789,72 ticks =  1,56 ms.

MapFromResolveUsingエルビス演算子よりも遅いNullReferenceExceptionsをキャッチする必要があります?.

于 2016-03-13T16:20:49.827 に答える
9

MapFromいくつかの余分なスマートがあります。例(メーリングリストから):

MapFromでは、子のプロパティを賢く掘り下げようとしています(通常のフラット化と同じように)。MapFromは、リダイレクトを許可するビットを追加して、平坦化を模倣する試みです。ResolveUsingにはこの動作はありません。

これがどこかで完全に文書化されているかどうかはわかりません(ソースコードを除く)。

于 2013-02-14T20:14:01.187 に答える
1

多くの場合、どちらも使用できますが、公式ドキュメントに基づくと、LINQプロジェクションに関しては違いがあります。詳細な説明はここにあります。

簡単に言うと、可能な限りMapFromを使用してください。

于 2016-04-07T11:09:12.317 に答える
0

ソースコードによると、ResolveUsingはもっと複雑です。ソース値は任意のオブジェクトにすることができます。したがって、指定されたオブジェクトを「解決」することで取得するintやboolなど、宛先メンバーに入力する任意の値を使用できます。ただし、MapFromメンバーを使用してマップするだけです。

/// <summary>
/// Resolve destination member using a custom value resolver callback. Used instead of MapFrom when not simply redirecting a source member
/// This method cannot be used in conjunction with LINQ query projection
/// </summary>
/// <param name="resolver">Callback function to resolve against source type</param>
void ResolveUsing(Func<TSource, object> resolver);

/// <summary>
/// Specify the source member to map from. Can only reference a member on the <typeparamref name="TSource"/> type
/// This method can be used in mapping to LINQ query projections, while ResolveUsing cannot.
/// Any null reference exceptions in this expression will be ignored (similar to flattening behavior)
/// </summary>
/// <typeparam name="TMember">Member type of the source member to use</typeparam>
/// <param name="sourceMember">Expression referencing the source member to map against</param>
void MapFrom<TMember>(Expression<Func<TSource, TMember>> sourceMember);
于 2014-02-19T09:18:12.323 に答える