AutoMapperを使用して、DTOオブジェクトとビジネスオブジェクトをマッピングしています。 AutoMapperConfiguration.csファイルが2つあります。1つはサービスレイヤーに、もう1つはWeb APIレイヤーにあります。
次のリンクの答えに示されているように AutoMapper.CreateMapsを配置する場所?
私はGlobal.asaxクラスでこれらの両方のファイルのConfigure()を呼び出しています
AutoMapperWebConfiguration.Configure();
AutoMapperServiceConfiguration.Configure();
しかし、私のサービス構成呼び出し(2番目の呼び出し)がWeb APIレイヤー(最初の呼び出し)のマッピングを上書きしているようで、マッピングが見つからないという例外が発生します。
このように構成呼び出しを逆にすると
AutoMapperServiceConfiguration.Configure();
AutoMapperWebConfiguration.Configure();
Web APIマッピングの例外は発生しませんが、サービスレイヤーの同じマッピング例外が発生します。
これは上記のスタックオーバーフローリンクで回答として明確にマークされているため、何か間違っていますか?
これが私のコードです:
public static class AutoMapperServiceConfiguration
{
public static void Configure()
{
Mapper.Initialize(x =>
{
x.AddProfile<CmciFlowTestToGenericFlowTestSimpleMappingProfile>();
x.AddProfile<FsrsFlowTestToGenericFlowTestSimpleMappingProfile>();
});
}
}
public class FsrsFlowTestToGenericFlowTestSimpleMappingProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<FsrsFlowTest, GenericFlowTest>()
.ConvertUsing<FsrsFlowTestToGenericFlowTestSimpleConverter>();
}
}
public class FsrsFlowTestToGenericFlowTestSimpleConverter : TypeConverter<FsrsFlowTest, GenericFlowTest>
{
protected override GenericFlowTest ConvertCore(FsrsFlowTest source)
{
if (source == null)
{
return null;
}
return new GenericFlowTest
{
FlowTestDate = source.FlowTestDates,
StaticPsi = source.HydrantStaticPsi.ToString(),
ResidualPsi = source.HydrantResidualPsi.ToString(),
TotalFlow = source.NffGallonsPerMinute.ToString(),
FlowTestLocation = source.FsrsFlowTestLocations.Any()
? source.FsrsFlowTestLocations.First().LocationDescription
: null
};
}
public class CmciFlowTestToGenericFlowTestSimpleMappingProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<CmciFlowTest, GenericFlowTest>()
.ConvertUsing<CmciFlowTestToGenericFlowTestSimpleConverter>();
}
}
public class CmciFlowTestToGenericFlowTestSimpleConverter : TypeConverter<CmciFlowTest, GenericFlowTest>
{
protected override GenericFlowTest ConvertCore(CmciFlowTest source)
{
if (source == null)
{
return null;
}
return new GenericFlowTest
{
FlowTestDate = source.FlowTestDates,
StaticPsi = source.HydrantStaticPsi.ToString(),
ResidualPsi = source.HydrantResidualPsi.ToString(),
TotalFlow = source.CalculatedHydrantGallonsPerMinute.ToString(),
FlowTestLocation = source.StaticLocationHydrantFlowPSI
};
}
}
public static class AutoMapperWebConfiguration
{
public static void Configure()
{
Mapper.Initialize(x =>
{
x.AddProfile<ServiceToWebApiMappingProfile>();
x.AddProfile<WebApiToServiceMappingProfile>();
});
}
}
public class ServiceToWebApiMappingProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<ServiceFlowTest, FlowTest>();
}
}
public class WebApiToServiceMappingProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<PropertyAddress, ServicePropertyAddress>();
}
}
この問題を回避するには、AutoMapperWebConfigurationクラスにサービスプロファイルを追加し、global.asaxでAutoMapperWebConfiguration.Configure()のみを呼び出します。
Mapper.Initializeを呼び出すと、マッパーがリセットされ、以前に行ったすべてのものがワイプされます。
AddProfileへの呼び出しを1つのMapper.Initialize呼び出しに移動すると、すべて正常に動作するはずです。
Mapper.Initialize(x =>
{
x.AddProfile<CmciFlowTestToGenericFlowTestSimpleMappingProfile>();
x.AddProfile<FsrsFlowTestToGenericFlowTestSimpleMappingProfile>();
x.AddProfile<ServiceToWebApiMappingProfile>();
x.AddProfile<WebApiToServiceMappingProfile>();
});
@GruffBunnyの答えは正しいですが、スケーラビリティのために少しすっきりさせようとしました(たとえば、多くの複雑なMapper.Initialize()
メソッドがあり、将来さらに追加する可能性がある場合)。
これを行うには、_AutoMapperConfiguration.cs
_ファイルのallに次の構造を実装します。
Mapper.Initialize()
メソッドから_Action<IConfiguration>
_をパブリックプロパティに抽出しますそれぞれをConfigAction
と呼びます。
_public static Action<IConfiguration> ConfigAction = new Action<IConfiguration>(x =>
{
x.AddProfile<SomeProfile>();
x.AddProfile<SomeOtherProfileProfile>();
//... more profiles
});
_
これにより、_Mapper.Initialize
_を呼び出す必要がある任意の場所からアクションを呼び出すことができます。
Mapper.Initialize()
内部Configure()
がこのプロパティを参照するようになりました_public static void Configure()
{
Mapper.Initialize(ConfigAction);
}
_
その後、Mapper.Initialize()
への単一の集中呼び出しで、すべての異なるConfigAction
sを呼び出すことができます
AutoMapperConfiguration.Configure()
のApplication_Start()
は、_Mapper.Initialize(x =>
{
Project1.AutoMapperConfiguration.ConfigAction.Invoke(x);
Project2.AutoMapperConfiguration.ConfigAction.Invoke(x);
Project3.AutoMapperConfiguration.ConfigAction.Invoke(x);
//... keep adding as your project grows
});
_
これにより、個々のMapper.Initialize()
呼び出しから中央の呼び出しにメソッド本体をコピーして貼り付ける必要がなくなります。 [〜#〜] dry [〜#〜]およびそれすべて。
AutoMapper 5.2と.NET Coreに対する@theyetimanの素晴らしい答えを更新する。
public static class AutoMapperConfiguration
{
public static void Configure()
{
Mapper.Initialize(ConfigAction);
}
public static Action<IMapperConfigurationExpression> ConfigAction = cfg =>
{
cfg.AddProfile<SomeProfile>();
cfg.AddProfile<SomeOtherProfileProfile>();
};
}
APIまたはWebスタートアップ。
public Startup(IHostingEnvironment env)
{
Mapper.Initialize(x =>
{
Project1.AutoMapperConfiguration.ConfigAction.Invoke(x);
Project2.AutoMapperConfiguration.ConfigAction.Invoke(x);
Project3.AutoMapperConfiguration.ConfigAction.Invoke(x);
});
}