【问题标题】:AutoMapper - converting string to enumAutoMapper - 将字符串转换为枚举
【发布时间】:2018-02-21 15:47:39
【问题描述】:

我使用 AutoMapper 已经有一段时间了,遇到了一个问题,我需要将一个对象映射到另一个对象(如下所示)。

型号:

public Guid guid { get; set; }
public string Status { get; set; }

使用 DTO 传输:

public Guid guid { get; set; }
public Status Status { get; set; }

枚举将包含:

public enum Status {

    Example,
    AnotherExample,
    PossibleExample

}

我已经设法在模型和 DTO 之间进行转换,但是,转换是否处理通过模型对象传入的字符串在 DTO 内的枚举中找不到的情况?我试过这个,发现我在转换时收到错误:

SomeExample ---> System.ArgumentException: Requested value 'SomeExample' was not found.
   at System.Enum.EnumResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument)
   at System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult)
   at System.Enum.Parse(Type enumType, String value, Boolean ignoreCase)
   at AutoMapper.Mappers.EnumMapper.Map(ResolutionContext context)
   at AutoMapper.MappingEngine.Map(ResolutionContext context)

传递错误字符串的示例:

{
    "guid": "42c1f9f7-a375-4a65-b883-e6e9717d18fe",
    "Status": "SomeExample"
}

如果我使用 Enum.Parse,我会假设如果它无法解析字符串,它会将其默认为枚举中的顶部索引?

编辑:这是用于将字符串转换为枚举的映射

CreateMap<Model, Dto>()
               .ForMember(d => d.Status, op => op.MapFrom(o => o.Status));

【问题讨论】:

  • 您是如何实现转换的?您是否使用不匹配的字符串对其进行了测试?
  • 你应该让那个枚举属性为空吗?
  • @OnkelToob 我已经更新了我原来的问题,以符合您的要求。

标签: c# automapper


【解决方案1】:

您可以指定自己的自定义解析器并确保它会得到安全处理。

http://automapper.readthedocs.io/en/latest/Custom-type-converters.html

.ForMember(x => x.someEnumValue, opt => opt.ResolveUsing(src =>
    {
        if (Enum.TryParse(typeof(Status), src.someStringValue, out var parsedResult))
            return parsedResult;
        return Status.Example;
    }))

使用 AutoMapper 配置文件的完整工作示例:

namespace MyProject.Domain.Mapping
{
    public enum Status
    {
        Unknown,
        Example,
        AnotherExample,
        PossibleExample
    }

    public class RecordPost
    {
        public Status Status { get; set; }
    }

    public class RecordDto
    {
        public string Status { get; set; }
    }

    public static class AutoMapperConfiguration
    {
        public static void Configure()
        {
            Mapper.Initialize(cfg =>
            {
                cfg.AddProfile(new RecordProfile());
            });

            Mapper.AssertConfigurationIsValid();
        }
    }

    public class RecordProfile : Profile
    {
        public RecordProfile()
        {
            CreateMap<RecordPost, RecordDto>()
                .ForMember(x => x.Status, opt => opt.MapFrom(src => src.Status.ToString()));

            CreateMap<RecordDto, RecordPost>()
                .ForMember(x => x.Status, opt => opt.ResolveUsing(src =>
                {
                    if (!Enum.TryParse(typeof(Status), src.Status, out var parsedResult))
                        return Status.Unknown;
                    return parsedResult;
                }));
        }
    }
}

【讨论】:

  • 感谢您的建议,但在尝试实施此操作时,我遇到了src 的问题,而且我无法访问所需的属性。我在这里做错了吗?
  • 听起来很像 - 如果可以,请将问题代码 sn-p 放在一个要点中并在此处发布链接。 gist.github.com
  • 添加了一个完整的例子 - 你已经接近但你跳过了几个步骤。
  • 我已经到了我知道我错过了什么的地步,但我看不到什么。据我所知,将我的代码与您的代码进行比较,它应该可以工作,但我根本没有选择使用src.Status。我所拥有的只是“值、类型、上下文”等属性。
  • 嗨杰克 - 主要问题是你需要两个单独的类。一个用于配置 AutoMapper,以及一个从 Profile 继承的单独的类,它定义了实际的映射。然后,您可以在父配置类中使用配置文件的实例 - 这种设计允许您为大型(或模块化)项目拆分映射。
猜你喜欢
  • 2010-10-03
  • 1970-01-01
  • 2014-03-18
  • 2015-06-10
  • 2012-08-25
  • 1970-01-01
  • 2016-07-30
  • 2012-12-07
相关资源
最近更新 更多