如何通过反射为程序集中的记录类型批量注册Dapper泛型类型处理器?
批量注册Dapper泛型类型处理器失败问题
我正在做底层逻辑处理,希望这是近期最后一次使用Reflection,之后回归高层开发。
已定义的类型与处理器
首先定义了主键泛型类型:
type PrimaryKey<'x> = | Id of int | EmptyPrimaryKey
接着定义关联数据库表的记录类型(示例):
type User = { user_id: PrimaryKey<User> username: string email: string address_id: PrimaryKey<Address> } with static member DatabaseTable = "users"
为Dapper编写了自定义主键类型处理器:
type PrimaryKeyHandler<'X>() = inherit SqlMapper.TypeHandler<PrimaryKey<'X>>() (* 暂时不考虑这部分逻辑是否可行 *) override _.SetValue(param, value) = let valueOrNull = match value with | PrimaryKey.Id id -> box id | EmptyPrimaryKey -> null param.Value <- valueOrNull override _.Parse value = if isNull value || value = box DBNull.Value then EmptyPrimaryKey else Id (value :?> int)
当前手动注册方式
目前需要为每个含主键的记录类型手动注册处理器:
SqlMapper.AddTypeHandler (PrimaryKeyHandler<User>()) SqlMapper.AddTypeHandler (PrimaryKeyHandler<OtherRecordType>())
批量注册的尝试与错误
我已经能筛选出所有关联数据库表的记录类型:
let RegisterTypeHandlers () = let assembly = Assembly.GetCallingAssembly() let handler = typedefof<PrimaryKeyHandler<_>> assembly.GetTypes() |> Seq.filter(fun t -> FSharpType.IsRecord(t) && t.GetProperty("DatabaseTable") <> null )
但尝试遍历这些类型批量调用AddTypeHandler时失败,完整代码如下:
let RegisterTypeHandlers () = let assembly = Assembly.GetCallingAssembly() let handler = typedefof<PrimaryKeyHandler<_>> assembly.GetTypes() |> Seq.filter(fun t -> FSharpType.IsRecord(t) && t.GetProperty("DatabaseTable") <> null ) |> Seq.iter(fun t -> printfn $"Type: {t.Name}" let ctor = handler .MakeGenericType(t) .GetConstructor(Array.empty) .Invoke(Array.empty) (typeof<SqlMapper>.GetMethods() |> Seq.filter(fun methodInfo -> if methodInfo.Name = "AddTypeHandler" && methodInfo.IsGenericMethodDefinition then let gp = methodInfo.GetParameters() not <| isNull gp && gp.Length = 1 && gp.[0].ParameterType.Name.Contains("TypeHandler") else false) |> Seq.head) .MakeGenericMethod(t) .Invoke(null, [| ctor |]) |> ignore )
报错信息:
Unhandled exception. System.ArgumentException: Object of type 'MyModule.Common+PrimaryKeyHandler`1[Program+User]' cannot be converted to type 'Dapper.SqlMapper+TypeHandler`1[Program+User]'.
我研究了反射泛型相关函数,但不知道后续该怎么解决。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

