如何在AutoMapper中将double转换为nullable int,int转换为nullable int?

时间:2015-05-21 05:23:33

标签: c# .net automapper

我不得不与此争吵一段时间。我使用AutoMapper在不同的数字格式之间进行映射,并在将int映射到int时不断出错?现在,我可以相应地修改我的DTO对象,但它并不那么容易。

我理解这主要是由于盒装类型而与AutoMapper无关,但很高兴看到更多支持类型转换(例如在所有AutoMapper都是辅助库之后强制隐式转换的标志)。 / p>

1 个答案:

答案 0 :(得分:2)

这里我们将使用自定义类型映射器:

Mapper.Initialize(cfg =>
{
    // Here we're going to use some custom type converters
    // The custom converter just forces a cast between two somewhat castable types using implicit conversion.
    cfg.CreateMap<int, int?>().ConvertUsing<CastableTypeConverter<int, int?>>();
    cfg.CreateMap<double, int?>().ConvertUsing<CastableTypeConverter<double, int?>>();
    cfg.CreateMap<short, int?>().ConvertUsing<CastableTypeConverter<short, int?>>();
    cfg.CreateMap<byte, int?>().ConvertUsing<CastableTypeConverter<byte, int?>>();
    cfg.CreateMap<double, int>().ConvertUsing<CastableTypeConverter<double, int>>();
    cfg.CreateMap<decimal, int>().ConvertUsing<CastableTypeConverter<decimal, int>>();
    cfg.CreateMap<decimal, double>().ConvertUsing<CastableTypeConverter<decimal, double>>();
    cfg.CreateMap<short, int>().ConvertUsing<CastableTypeConverter<short, int>>();
    cfg.CreateMap<byte, int>().ConvertUsing<CastableTypeConverter<byte, int>>();
    /*...*/
});


/// <summary>
/// This just forces implicit casting between two types (that are castable!)
/// Such as (int) to (int?), or (double) to (int)
/// </summary>
/// <typeparam name="TSrc"></typeparam>
/// <typeparam name="TDst"></typeparam>
private class CastableTypeConverter<TSrc, TDst> : TypeConverter<TSrc, TDst>
{
    protected override TDst ConvertCore(TSrc source)
    {
        Type srcType = typeof(TSrc);
        Type destType = typeof(TDst);
        TDst result = Activator.CreateInstance<TDst>();
        // a syntactical optimization
        object src = source;
        object dst = source;
        if (destType.IsGenericType && destType.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            // get the underlying type
            destType = Nullable.GetUnderlyingType(destType);
        }

        // trying to cast to nullable type from non-nullable type,
        // or an implicit cast is required.
        if (destType == typeof(int) && srcType == typeof(decimal))
            dst = (int)(decimal)src;
        if (destType == typeof(int) && srcType == typeof(double))
            dst = (int)(double)src;
        if (destType == typeof(int) && srcType == typeof(float))
            dst = (int)(float)src;
        if (destType == typeof(int) && srcType == typeof(short))
            dst = (int)(short)src;
        if (destType == typeof(int) && srcType == typeof(byte))
            dst = (int)(byte)src;
        if (destType == typeof(int) && srcType == typeof(int))
            dst = (int)src;



        // now try to cast it appropriately
        try
        {
            result = (TDst)dst;
        }
        catch (Exception)
        {
            throw;
        }
        return result;
    }
}

您将看到我正在进行双重隐式演员 - 第一个打开类型,第二个打开目标类型。如果目标类型可以为空,则它不会爆炸,因为它已经被强制转换为基类型。最后,如果没有指定自定义转换,它将尝试隐式转换并可能爆炸(意图!)

当然 - 我并没有说你应该继续为你的所有数据类型做这件事。但我不会告诉你如何编码,只是如何解决这个特殊问题。这里的正确答案是匹配您的DTO对象数据类型,只需说&#39;