上下文:
我正在尝试创建几个类来封装SQL命令,使其比标准System.Data
类更适合函数式编程。
我关心3种主要的SQL命令类型
必须如何执行这些实现的实现略有不同,但是我希望它们都共享一个公共协定,这就是为什么我要使用类继承。我也可以使用接口,但是在这种情况下似乎没有太大的区别。
我已将共享合同作为此基础类实现:
[<AbstractClass>]
type ClosedCommand<'a>(text, kind, parameters) =
inherit OpenCommand(text, kind, parameters)
abstract member execute : cn:IDbConnection -> 'a
3个子类为:
type UnitCommand(text, kind, parameters) =
inherit ClosedCommand<unit>(text, kind, parameters)
override x.execute cn =
let cmd = x.toCommandDefinition null
SqlMapper.Execute(cn, cmd) |> ignore
type SingleCommand<'a>(text, kind, parameters) =
inherit ClosedCommand<'a>(text, kind, parameters)
override x.execute cn =
let cmd = x.toCommandDefinition null
SqlMapper.QuerySingle<'a>(cn, cmd)
type PluralCommand<'a>(text, kind, parameters) =
inherit ClosedCommand<seq<'a>>(text, kind, parameters)
override x.execute cn =
let cmd = x.toCommandDefinition null
SqlMapper.Query<'a>(cn, cmd)
实现的核心是Dapper库中的SqlMapper
类。
问题:
对于没有返回任何命令的命令,我在子类上遇到编译错误。这是屏幕截图:
消息是:
成员execute : IDbConnection -> unit
的类型不正确,无法覆盖相应的抽象方法。
在我看来,它确实具有正确的类型。即使我添加类型注释,它仍然会给出相同的错误。
这种情况与其他两种情况之间的唯一区别是,它将unit
绑定到'a
,而其他两种情况则保持通用。似乎并不重要。
最小示例:
[<AbstractClass>]
type CommandBase<'a>(name) =
member this.Name : string = name
abstract member Execute : unit -> 'a
type UnitCommand(name) =
inherit CommandBase<unit>(name)
override this.Execute () = ()
type SingleCommand<'a>(name, x) =
inherit CommandBase<'a>(name)
override this.Execute () = x
type MultipleCommand<'a>(name, xs) =
inherit CommandBase<seq<'a>>(name)
override this.Execute () = xs
如何获取此文件?