59

我有一个面向公众的界面,我试图将两个不同的枚举相互映射。我尝试使用以下代码:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>();

当那不起作用时,我尝试了:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>().ConvertUsing(x => (Common.ValidationResultType)((int)x));

但这似乎也不起作用。反正有没有让自动映射器来处理这种情况?

4

9 回答 9

77

除了编写自定义转换器,只需使用 ConvertUsing()

Mapper.CreateMap<EnumSrc, EnumDst>().ConvertUsing((value, destination) => 
{
    switch(value)
    {
        case EnumSrc.Option1:
            return EnumDst.Choice1;
        case EnumSrc.Option2:
            return EnumDst.Choice2;
        case EnumSrc.Option3:
            return EnumDst.Choice3;
        default:
            return EnumDst.None;
    }
});
于 2015-07-08T16:31:26.950 回答
58

您不需要为枚举类型执行 CreateMap。只要去掉 CreateMap 调用,它就可以工作,只要枚举类型之间的名称和/或值匹配。

于 2012-06-29T20:43:32.727 回答
18

我的 Automapper 以这种方式工作:

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

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

于 2016-05-24T19:13:37.833 回答
6

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

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

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;
        }
    }
}
于 2015-04-16T11:48:27.290 回答
6

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

我的 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 和 JudgmentType 是枚举。它们的相关视图模型是 ProblemTypeViewModel 和 JudgmentTypeViewModel,它们的成员与其相关模型相同。

虽然我没有测试,但我认为下面的行应该适合你:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>()
           .ForMember(m=> m, opt => opt.MapFrom(x=> (Common.ValidationResultType)(int)x);

希望它有所帮助。

于 2015-10-14T07:46:28.590 回答
4

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

第一步是像这样设置 Mapper 配置:

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;
        }
    }
}

我们只需switch通过源 Enum 的值并任意返回适当的目标 Enum 值。AutoMapper 负责其余的工作。

于 2015-02-11T18:00:48.847 回答
3

只需为两个枚举创建一个映射器,就是这样!Automapper 将通过 Enum 的匹配值或索引值进行映射。(例如草稿 -> Step1)

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);



    }
}
于 2016-02-19T05:52:31.930 回答
2

我试图使用 Automapper 在“相等”枚举之间进行映射,但不幸的是它不起作用。我怀疑问题是外壳不同:

public enum Foo {
    val1,
    val2
}

public enum Bar {
    Val1,
    Val2
}

Foo是从 XSD 自动生成的东西,供应商很烂。还有三十多岁的价值,我不想把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;
}

当然,这只适用于您的枚举只有大小写不同的情况。您可以通过清理输入字符串(例如删除下划线等)或根据需要向其中添加内容来使其更加精细。

于 2015-11-09T15:08:13.267 回答
2

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

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
    }
}
于 2021-01-08T09:02:38.563 回答