Если вы хотите использовать подход, основанный на дискриминационных союзах, то я думаю, что объявление более подходит (так как вам не нужно манипулировать цитатами).Небольшая модификация типа, предложенного Алексом:
type PropertyInfo<'a> =
| String of Expr<'a -> string>
| Date of Expr<'a -> System.DateTime>
| ...
Тогда вы напишите что-то вроде:
let property (pi:PropertyInfo<'a>) (cfg:EntityInfo<'a>) =
match pi with
| String e -> cfg.Property e
| ...
cfg |> property (String <@ fun e -> e.Foo @>)
Другой вариант - реализовать property
как статический члентип, в этом случае вы можете использовать обычную перегрузку (аналогично C #).Что-то вроде:
type EF =
static member property (expr:Expr<'a -> string>) (cfg:EntityInfo<'a>) =
cfg.Property expr
static member property (expr:Expr<'a -> System.DateTime>) (cfg:EntityInfo<'a>) =
cfg.Property expr
static member property (expr:Expr<'a -> System.Byte>) (cfg:EntityInfo<'a>) =
cfg.Property expr
Тогда вы напишите:
cfg |> EF.property <@ e -> e.Foo @>
Наконец, вы также можете сделать его немного проще (но менее безопасным), сделав функцию полностью универсальной и выполнивтест динамического типа (чтобы решить, какой тип возврата используется).Что-то вроде:
let property<'a, 'r> (e:Expr<'a -> 'r>) (cfg:EntityInfo<'a>) =
if typeof<'r> = typeof<string> then
// ...