2つの異なる列挙を相互にマッピングしようとしている公開インターフェイスがあります。私は次のコードを使用しようとしました:
Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>();
それがうまくいかなかったとき、私は試しました:
Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>().ConvertUsing(x => (Common.ValidationResultType)((int)x));
しかし、それでもうまくいかないようです。とにかくオートマッパーにこのシナリオを処理させる方法はありますか?
列挙型に対してCreateMapを実行する必要はありません。名前や値が列挙型間で一致する限り、CreateMap呼び出しを取り除くだけで機能します。
カスタムコンバーターを記述する代わりに、ConvertUsing()を使用するだけです
Mapper.CreateMap<EnumSrc, EnumDst>().ConvertUsing(value =>
{
switch(value)
{
case EnumSrc.Option1:
return EnumDst.Choice1;
case EnumSrc.Option2:
return EnumDst.Choice2;
case EnumSrc.Option3:
return EnumDst.Choice3;
default:
return EnumDst.None;
}
});
私のAutomapperは次のように機能します。
マップを作成する場合: Automapperは、名前が完全に一致する場合でも、値によって列挙型を一致させます。
マップを作成しない場合: Automapperは、名前で列挙型を照合します。
私にとって最も簡単な方法は次のとおりです。
私のEnumは別のクラスにネストされているため、以下のようにForMemberメソッドとMapFromを使用します。
Mapper.CreateMap<ProblematicCustomer, ProblematicCustomerViewModel>()
.ForMember(m=> m.ProblemType, opt=> opt.MapFrom(x=> (ProblemTypeViewModel)(int)x.ProblemType))
.ForMember(m=> m.JudgmentType, opt=> opt.MapFrom(x=> (JudgmentTypeViewModel)(int)x.JudgmentType));
ProblemTypeとJudgementTypeはEnumです。また、関連するビューモデルはProblemTypeViewModelとJudgmentTypeViewModelであり、関連するモデルと同じメンバーです。
私はテストしませんが、以下の行があなたのために働くはずだと思います:
Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>()
.ForMember(m=> m, opt => opt.MapFrom(x=> (Common.ValidationResultType)(int)x);
それが役立つことを願っています。
2つのEnumのマッパーを作成するだけです! Automapperは、一致する値またはEnumのインデックス値によってマップします。 (例:ドラフト->ステップ1)
public enum SourceStatus
{
Draft,
Submitted,
Deleted
}
public enum DestinationStatus
{
Step1,
Step2,
Step3
}
public class SourceObj
{
public SourceStatus Status { get; set; }
}
public class DestinationObj
{
public DestinationStatus Status { get; set; }
}
class Program
{
static void Main(string[] args)
{
//Static APi style - this is obsolete now. From Version 5.0 onwards this will be removed.
SourceObj mySrcObj = new SourceObj();
mySrcObj.Status = SourceStatus.Deleted;
Mapper.CreateMap<SourceStatus, DestinationStatus>();
Mapper.CreateMap<SourceObj, DestinationObj>();
DestinationObj myDestObj = Mapper.Map<SourceObj, DestinationObj>(mySrcObj);
//New way of doing it
SourceObj mySrcObj2 = new SourceObj();
mySrcObj2.Status = SourceStatus.Draft;
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<SourceObj, DestinationObj>();
});
IMapper mapper = config.CreateMapper();
var source = new SourceObj();
var dest = mapper.Map<SourceObj, DestinationObj>(source);
}
}
ここでの他の答えは私にはうまくいきませんでした。
以下を実装するクラスを作成する必要があります。
ITypeConvertor<SourceType ,DestinationType>
例として
Mapper.CreateMap<EnumType1.VatLevel, EnumType2.VatRateLevel>()
.ConvertUsing(new VatLevelConvertor());
そしてクラス:
internal class VatLevelConvertor : ITypeConverter<EnumType1.VatLevel, EnumType2.VatRateLevel>
{
public EnumType2.VatRateLevel Convert(ResolutionContext context)
{
EnumType1.VatLevel value = (EnumType1.VatLevel)context.SourceValue;
switch (value)
{
case EnumType1.VatLevel.Standard:
return EnumType2.VatRateLevel.Normal;
case EnumType1.VatLevel.Reduced:
return EnumType2.VatRateLevel.Lower;
case EnumType1.VatLevel.SuperReduced:
return EnumType2.VatRateLevel.Other;
default:
return EnumType2.VatRateLevel.Other;
}
}
}
AutoMapperを使用したまま、値が異なる2つのEnum型の間で変換を行う可能性が1つあります。私の場合、Enum型はAutoMapperによって変換される他のエンティティのプロパティであるため、AutoMapperを使用する必要がありました。これらのエンティティにAutoMapperを使用することが要件でした。
最初のステップは、マッパー構成を次のようにセットアップすることです。
_Mapper.CreateMap<EnumSrc, EnumDst>()
.ConstructUsing(EnumConversion.FromSrcToDst);
_
.ConstructUsing(...)
を呼び出すと、変換を行うための独自のメソッドを渡すことができます。変換の方法は非常に簡単です。
_public class EnumConversion
{
internal static EnumDst FromSrcToDst(ResolutionContext arg)
{
EnumSrc value = (EnumSrc)arg.SourceValue;
switch(value)
{
case EnumSrc.Option1:
return EnumDst.Choice1;
case EnumSrc.Option2:
return EnumDst.Choice2;
case EnumSrc.Option3:
return EnumDst.Choice3;
default:
return EnumDst.None;
}
}
}
_
ソースEnumの値を単にswitch
して、適切な宛先Enum値を任意に返します。 AutoMapperが残りを処理します。
Automapperを使用して「等しい」列挙型間をマッピングしようとしましたが、残念ながら機能しませんでした。私は問題がケーシングの違いだと思う:
public enum Foo {
val1,
val2
}
public enum Bar {
Val1,
Val2
}
Foo
はXSDから自動生成されたものであり、サプライヤは気の毒です。また、30の値があり、非常にばかげたもののために、その大きさのswitch
をどこにも入れたくありませんでした。
私が取ったアプローチは、ソース値を文字列に変換し、それを宛先値として解析することでした:
static Foo ConvertEnum(Bar source)
{
Foo result;
var parsed = Enum.TryParse(source.ToString().ToLowerInvariant(), true, out result);
if(!parsed)
// throw or return default value
throw new ArgumentOutOfRangeException("source", source, "Unknown source value");
return result;
}
もちろん、これは列挙型の大文字と小文字が異なる場合にのみ機能します。入力文字列をクリーンアップする(たとえば、アンダースコアを削除するなど)か、必要に応じて何かを追加することで、より複雑にすることができます。