使用自定义SqlMapper.ITypeHandler将Enum映射到字符串列-Dapper

wwa*_*rby 5 c# orm enums dapper

我有大量的PL / SQL存储过程,它们返回带有单个字符串的列,这些字符串表示固定范围内的某种状态值。在我正在处理的项目中,Dapper已将这些列映射到域对象上的字符串属性,这些属性笨拙且难以管理,因此我想切换到枚举。

如果我使用带有单个字符名称的枚举,例如enum Foo {A, P}我很确定Dapper可以正确地映射它们,但是我不希望那样,那么我想要具有描述性标签的枚举,例如:

enum Foo {
    [StringValue("A")]
    Active,
    [StringValue("P")]
    Proposed
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,StringValueAttribute是一个自定义属性,我可以使用反射将转换"A"Foo.Active,它可以正常工作-除非我需要Dapper来为我执行该转换逻辑。我编写了一个自定义类型处理程序来执行此操作:

public class EnumTypeHandler<T> : SqlMapper.TypeHandler<T>
{
    public override T Parse(object value)
    {
        if (value == null || value is DBNull) { return default(T); }
        return EnumHelper.FromStringValue<T>(value.ToString());
    }

    public override void SetValue(IDbDataParameter parameter, T value)
    {
        parameter.DbType = DbType.String;
        parameter.Value = EnumHelper.GetStringValue(value as Enum);
    }
}

//Usage:
SqlMapper.AddTypeHandler(typeof(Foo),
    (SqlMapper.ITypeHandler)Activator.CreateInstance(typeof(EnumTypeHandler<>).MakeGenericType(typeof(Foo)));
Run Code Online (Sandbox Code Playgroud)

的注册SqlMapper.AddTypeHandler()似乎可以正常工作,但是当我的DbConnection.Query()代码运行时,我收到一条错误消息,提示无法转换值'A'-该错误是从Enum.Parse引发的,这表明Dapper实际上并未调用我的类型处理程序尽管已被注册。有谁知道解决这个问题的方法吗?

wwa*_*rby 2

另一位用户在 Dapper 的 github 网站上将此问题报告为问题。似乎这是专门针对 Dapper 中的枚举进行的有意优化,因此我更改了数据库模型,而不是尝试更改映射代码。我试图修改 Dapper 本身,但 Dapper 的源代码经过了我从未见过的优化,发出操作码以尽可能高效的方式执行转换 - 我不想开始尝试弄清楚如何制作那里发生变化。