そのため、通常の DTO からビジネスへのマッパー以外に何かがあり、最小限のマッピング コードでそれらをマッピングしようとしています。
設定
public class Target {
public string propA { get; set; }
public string propB { get; set; }
public string propC { get; set; }
public string propD { get; set; }
public string propE { get; set; }
public List<KeyValuePair> Tokens { get; set; }
}
public class Source {
public SomeClass SomeClass { get; set; }
public AnotherClass AnotherClass { get; set; }
}
public class SomeClass {
public string propA { get; set; }
public string propB { get; set; }
public string propDifferent { get; set; }
public List<KeyValuePair> Tokens { get; set; }
}
public class AnotherClass {
public string propC { get; set; }
public string propD { get; set; }
public List<KeyValuePair> Tokens { get; set; }
}
マッパー構成
Mapper.CreateMap<SomeClass, Target>()
.ForMember(dest => dest.propE, opt => opt.MapFrom(src => src.propDifferent));
Mapper.CreateMap<AnotherClass, Target>();
Mapper.CreateMap<Source, Target>()
.ForMember(dest => dest, opt => opt.MapFrom(src => src.SomeClass))
.ForMember(dest => dest, opt => opt.MapFrom(src => src.AnotherClass));
これを行うとスローされます
エラー: AutoMapper.AutoMapperConfigurationException: メンバーのカスタム構成は、型の最上位の個々のメンバーに対してのみサポートされています。
また、 を取りAnotherClass.Tokens
、SomeClass.Tokens
に追加する必要がありTarget.Tokens
ます。
使用できることはわかっています.ConvertUsing
が、すべてのプロパティのマッピングを定義する必要があり、プロパティを一致させるための規則ベースのマッピングの利点が失われます。
.ConvertUsing
これを達成する他の方法はありますか(またはすべてのプロパティを手動でマッピングする以外に)?
Automapper経由でない場合、 EmitMapper経由で実行できますか? Tokens リストへの追加は、おそらく EmitMapper のPostProcessing
.
アップデート
少しハッキングした後、方法を見つけました:
public static IMappingExpression<TSource, TDestination> FlattenNested<TSource, TNestedSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof(TNestedSource);
var destinationType = typeof(TDestination);
var sourceProperties = sourceType.GetProperties().ToDictionary(x => x.Name.ToLowerInvariant());
var childPropName = typeof (TSource).GetProperties().First(x => x.PropertyType == sourceType).Name;
var mappableProperties = destinationType.GetProperties()
.Where(p => sourceProperties.ContainsKey(p.Name.ToLowerInvariant()) &&
sourceProperties[p.Name.ToLowerInvariant()].PropertyType ==
p.PropertyType)
.Select(p => new {DestProperty = p.Name, SrcProperty = sourceProperties[p.Name.ToLowerInvariant()].Name});
foreach (var property in mappableProperties)
{
expression.ForMember(property.DestProperty,
opt => opt.MapFrom(src => src.GetPropertyValue(childPropName).GetPropertyValue(property.SrcProperty)));
}
return expression;
}
注:一致Name.ToLowerInvariant()
できるようにするためにAccountID
->AccountId
などを行います。
使用法
AutoMapper.Mapper.CreateMap<Source, Target>()
.FlattenNested<Source, SomeClass, Target>()
.FlattenNested<Source, AnotherClass, Target>()
.ForMember(dest => dest.propE, opt => opt.MapFrom(src => src.propDifferent));
IMappingExpression
この多くを使用してクリーンアップできる可能性があるという点で、他のプロパティをいくつか見つけました。見つけ次第更新します。