使用Automapper将字符串映射到枚举类型

7
我的问题是将从数据库返回的Linq2Sql对象转换为Viewmodel并进行填充。我们在几个区域中已经完成了这项工作,并且已经制定了一个很好的分层模式,但最新的项目需要使用一些枚举类型,这给我们带来了很多麻烦。目前,我们从数据库中获取数据,然后使用Automapper将数据转换(或展开)到Viewmodels中,但是将枚举类型添加到模型中似乎会导致Automapper出现问题。我尝试创建自定义解析器以满足所有其他映射需求,但在这种情况下无效。
代码示例如下:
public class CustomerBillingTabView{
    public string PaymentMethod {get; set;}
    ...other details
}

public class BillingViewModel{
    public PaymentMethodType PaymentMethod {get; set;}
    ...other details
}

public enum PaymentMethodType {
    Invoice, DirectDebit, CreditCard, Other
}

public class PaymentMethodTypeResolver : ValueResolver<CustomerBillingTabView, PaymentMethodType>
{
    protected override PaymentMethodType ResolveCore(CustomerBillingTabView source)
    {

        if (string.IsNullOrWhiteSpace(source.PaymentMethod))
        {
            source.PaymentMethod = source.PaymentMethod.Replace(" ", "");
            return (PaymentMethodType)Enum.Parse(typeof(PaymentMethodType), source.PaymentMethod, true);
        }

        return PaymentMethodType.Other;
    }
}

        CreateMap<CustomerBillingTabView, CustomerBillingViewModel>()
        .ForMember(c => c.CollectionMethod, opt => opt.ResolveUsing<PaymentMethodTypeResolver>())

我收到了以下错误信息。
[ArgumentException: Type provided must be an Enum.
Parameter name: enumType]
   System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult) +9626766
   System.Enum.Parse(Type enumType, String value, Boolean ignoreCase) +80
   AutoMapper.Mappers.EnumMapper.Map(ResolutionContext context, IMappingEngineRunner mapper) +231
   AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) +720

我希望在所有映射操作中都使用Automapper,但我看到很多人说它不能做这种类型的映射,所以我开始怀疑我是否使用错误?此外,我看到一些关于ValueInjecter的提及 - 这是Automapper的替代品,还是仅用于填补模型的水分并使用Automapper进行展平?
是的,我可以在我的ViewModel中使用字符串,但我不喜欢魔术字符串,而且这个特定项被助手用于在许多地方执行一些逻辑。

在仔细查看源代码和我的模型示例后,我意识到了几个问题。首先,由于某种原因,我把ViewModel上的枚举属性设为了可为null,这导致了主要的问题??!! 其次,我没有考虑我们视图返回的空格,在"Direct Debit"应该是DirectDebit。一旦我解决了这些问题,Automapper就能自动完成其工作,而无需自定义解析器等... 哇哦 - Andy Allison
+1 提及 ValueInjecter ;) - Omu
2个回答

10

这是关于 AutoMapper 文档的问题。如果你下载 AutoMapper 的源代码,那里面有一些示例。你想要的代码应该像这样:

public class PaymentMethodTypeResolver : ValueResolver<CustomerBillingTabView, PaymentMethodType>
{
    protected override PaymentMethodType ResolveCore(CustomerBillingTabView source)
    {

        string paymentMethod = source.Context.SourceValue as string;

        if (string.IsNullOrWhiteSpace(paymentMethod))
        {
            paymentMethod  = paymentMethod.Replace(" ", "");
            return source.New((PaymentMethodType)Enum.Parse(typeof(PaymentMethodType), paymentMethod, true));
        }

        return source.New(PaymentMethodType.Other);
    }
}

谢谢Jason。我去尝试你的解决方案,但是我不明白.Context.SourceValue和source.New是从哪里来的?我错过了什么吗?抱歉,我知道我有点新手。 - Andy Allison
嗨,Jason,感谢你的指引。如果你看到我上面的评论,我已经解决了问题,不需要自定义解析器。还是非常感谢你的帮助,并指向示例,这对我很有帮助。 - Andy Allison

5
这里有一个使用ValueInjecter的解决方案: 由于您已经解决了问题,我只是想指向类似的东西:AutoMapper strings to enum descriptions 在这个问题中,要求不仅仅是从字符串到枚举的转换,但它也包括了这种转换。
关于ValueInjecter作为替代方案:是的,它可以处理更通用的事情,无需为每个小事情配置,并构建您能想象到的任何约定。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接