F# - 类型约束。任何带有 属性 "id" 或通过字符串获取 属性 的记录
F# - Type Constraints. Any Record with property "id" or get property by string
我在实体库中有一个函数 - 基本上你可以将任何类型的记录传递给它,只要该类型具有 属性 id。
我正在使用这个,它以某种方式完美运行:
let inline Update (record: ^x) =
let tableName = GetDatabaseTable<'x> (*E.g if record is of type User, it returns the users table *)
let id = ((^x) : (member id : int) record)
update {
table tableName
set record
where (eq "id" id)
excludeColumn "id"
}
|> db.Update
然而,当我尝试添加另一个也采用泛型类型参数的函数时,该约束停止工作:
(*
Pass in a User record of {id=1, name="Username", usergroup_id=2}
and a type argument of <order> and it should return
all orders with a "user_id" value of 1.
*)
let inline GetAllRelated<'x> (record: ^y) =
let id = ((^y) : (member id : int) record) (*Causes an error, type constraint mismatch*)
let tableName = GetDatabaseTable<'x>
let columnName = nameof<'x> + "_id"
select {
table tableName
where (eq columnName id)
} |> db.Select<'x>
Type constraint mismatch when applying the default type 'obj' for a type inference variable. The type 'obj' does not support the operator 'get_id' Consider adding further type constraints
同时将 ^y 约束为一个对象。
对于未来的功能,我还希望能够动态访问记录 属性,我假设这可能通过反射实现,但不确定具体如何实现。仅使用 getProperty?
例如一个类似于
的函数
let GetRelated<'x> (record: 'y) =
let columnToGet = nameof<'x> + "_id"
(*
If you do something like
GetRelated<usergroup> {id=1, name="Username", usergroup_id=2}
then that should get the property "usergroup_id" of the passed in record.
*)
这东西可以做吗?我知道这有点简陋。
问题是你的函数实际上会有更多的类型参数,所以你可以指定 none 个或全部,但如果你只指定一个,它会强制其他类型参数为 obj
这就是这里发生的事情。
一个可能的解决方案是这样写:
let inline GetRelated<'x, ^y when ^y: (member id: int) > (record: 'y) = ...
我在实体库中有一个函数 - 基本上你可以将任何类型的记录传递给它,只要该类型具有 属性 id。
我正在使用这个,它以某种方式完美运行:
let inline Update (record: ^x) =
let tableName = GetDatabaseTable<'x> (*E.g if record is of type User, it returns the users table *)
let id = ((^x) : (member id : int) record)
update {
table tableName
set record
where (eq "id" id)
excludeColumn "id"
}
|> db.Update
然而,当我尝试添加另一个也采用泛型类型参数的函数时,该约束停止工作:
(*
Pass in a User record of {id=1, name="Username", usergroup_id=2}
and a type argument of <order> and it should return
all orders with a "user_id" value of 1.
*)
let inline GetAllRelated<'x> (record: ^y) =
let id = ((^y) : (member id : int) record) (*Causes an error, type constraint mismatch*)
let tableName = GetDatabaseTable<'x>
let columnName = nameof<'x> + "_id"
select {
table tableName
where (eq columnName id)
} |> db.Select<'x>
Type constraint mismatch when applying the default type 'obj' for a type inference variable. The type 'obj' does not support the operator 'get_id' Consider adding further type constraints
同时将 ^y 约束为一个对象。
对于未来的功能,我还希望能够动态访问记录 属性,我假设这可能通过反射实现,但不确定具体如何实现。仅使用 getProperty?
例如一个类似于
的函数let GetRelated<'x> (record: 'y) =
let columnToGet = nameof<'x> + "_id"
(*
If you do something like
GetRelated<usergroup> {id=1, name="Username", usergroup_id=2}
then that should get the property "usergroup_id" of the passed in record.
*)
这东西可以做吗?我知道这有点简陋。
问题是你的函数实际上会有更多的类型参数,所以你可以指定 none 个或全部,但如果你只指定一个,它会强制其他类型参数为 obj
这就是这里发生的事情。
一个可能的解决方案是这样写:
let inline GetRelated<'x, ^y when ^y: (member id: int) > (record: 'y) = ...