如何使用Automapper在两个枚举之间进行映射?

Jef*_*ott 49 c# automapper

我有一个面向公众的界面,我试图将两个不同的枚举映射到彼此.我试着使用以下代码:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>();
Run Code Online (Sandbox Code Playgroud)

当那不起作用时,我试过:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>().ConvertUsing(x => (Common.ValidationResultType)((int)x));
Run Code Online (Sandbox Code Playgroud)

但这似乎也不起作用.反正有没有让automapper来处理这种情况?

Tho*_*lin 62

或者编写自定义转换器,只需使用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;
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 您必须匹配表达式签名,在这种情况下,上面的示例缺少“destination”参数。将 `value =&gt;` 替换为 `(value, destination) =&gt;` 将解决该问题。 (3认同)
  • 我正在使用 `ConstructUsing` 并且它以某种方式返回错误的枚举,即使我的代码是一个巨大的 switch 语句返回正确的枚举。使用 `ConvertUsing` 解决了这个问题。 (2认同)
  • 这应该被标记为最佳答案。 (2认同)
  • 如果尝试这种方法,则会出现“带有语句主体的lambda表达式无法转换为表达式树”错误...虽然这种方法很棒。 (2认同)

Jim*_*ard 43

您不需要为枚举类型执行CreateMap.只要名称和/或值在枚举类型之间匹配,就可以去除CreateMap调用并且它应该可以工作.

  • "你不需要用Y做X"不是"如何用Y做X"的答案.当然,问Y是否真的有必要从来没有伤害 - 通常不是. (14认同)
  • 如果名称和值不匹配怎么办? (11认同)
  • @threed的问题是"如何使用AutoMapper映射两个枚举".我的答案是答案.关于OP尝试的事情,问题的其余部分开始走错了路.我的回答让他们走上了正确的道路. (9认同)
  • 然后,您需要创建一个自定义类型转换器。 (2认同)

Pio*_*tek 11

我的Automapper以这种方式工作:

如果我创建了一个地图: Automapper将按值匹配枚举,即使名称完全匹配.

如果我不创建地图: Automapper将按名称匹配枚举.


Tre*_*vor 5

这是在两个具有不同值的 Enum 类型之间进行转换的一种可能性,同时仍然使用 AutoMapper。就我而言,我需要使用 AutoMapper,因为 Enum 类型是由 AutoMapper 转换的其他实体的属性;要求对这些实体使用 AutoMapper。

第一步是设置 Mapper 配置,如下所示:

Mapper.CreateMap<EnumSrc, EnumDst>()
    .ConstructUsing(EnumConversion.FromSrcToDst);
Run Code Online (Sandbox Code Playgroud)

调用.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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我们只需switch通过源 Enum 的值并任意返回适当的目标 Enum 值。AutoMapper 会处理剩下的事情。


Nei*_*eil 5

这里的其他答案对我不起作用。

您需要创建一个实现的类:

ITypeConvertor<SourceType ,DestinationType>
Run Code Online (Sandbox Code Playgroud)

所以作为一个例子

 Mapper.CreateMap<EnumType1.VatLevel, EnumType2.VatRateLevel>()
       .ConvertUsing(new VatLevelConvertor());
Run Code Online (Sandbox Code Playgroud)

和班级:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


mes*_*sut 5

我发现对我有用的最简单方法如下:

我的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));
Run Code Online (Sandbox Code Playgroud)

ProblemType和JudgmentType是枚举。它们的相关视图模型是ProblemTypeViewModel和JudgmentTypeViewModel,其成员与相关模型相同。

虽然我没有测试,但是我认为下面的代码应该对您有用:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>()
           .ForMember(m=> m, opt => opt.MapFrom(x=> (Common.ValidationResultType)(int)x);
Run Code Online (Sandbox Code Playgroud)

希望对您有所帮助。


Jér*_*VEL 5

我知道这个问题很老了,但是如果像我这样的人路过这里......

AutoMapper 文档中,现在有一个AutoMapper.Extensions.EnumMapping Nuget 包提供了一种简单的方法来实现这一点。

引用 AutoMapper 文档:


public enum Source
{
    Default = 0,
    First = 1,
    Second = 2
}

public enum Destination
{
    Default = 0,
    Second = 2
}

internal class YourProfile : Profile
{
    public YourProfile()
    {
        CreateMap<Source, Destination>()
            .ConvertUsingEnumMapping(opt => opt
                // optional: .MapByValue() or MapByName(), without configuration MapByValue is used
                .MapValue(Source.First, Destination.Default)
            )
            .ReverseMap(); // to support Destination to Source mapping, including custom mappings of ConvertUsingEnumMapping
    }
}
Run Code Online (Sandbox Code Playgroud)