如何在 AutoMapper 中将 double 转换为可为空的 int,将 int 转换为可为空的 int?

How to convert double to nullable int, int to nullable int in AutoMapper?

我不得不为此奋斗了一段时间。我正在使用 AutoMapper 在不同的数字格式之间进行映射,并且在将 int 映射到 int 时不断出错?等。现在,我可以修改我的 DTO 对象以进行相应的匹配,但这并不容易。

我知道这主要是由于盒装类型,与 AutoMapper 无关,但很高兴看到对类型转换的更多支持(例如强制隐式转换的标志,毕竟 AutoMapper 是一个辅助库) .

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

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 对象数据类型,只需说'