我希望将结果发送到一个方法,该方法将内容输出到控制台/日志
我曾希望检测结果是否包含IEnumerable并遍历该集合以获取其结果。
这无法识别seq,只是简单地将其标识为Other Object。
抱歉,我太罗嗦了。
let rec LogResultGeneric (logInfo: string -> unit, logError: string -> unit) (result: Result<_, _>) =
let innerSelect (item: _) =
match item |> box with
| :? Result<_, _> as res ->
"RESULT" |> logInfo
res |> LogResultGeneric(logInfo, logError)
| _ ->
"VALUE" |> logInfo
item |> LogValueGeneric logInfo
"DISPLAY OUTCOME : " + result.ToString() |> logInfo
match result with
| Error msg ->
"ERROR RESULT" |> logError
match msg |> box with
| :? string as msg -> msg |> logError
| _ -> msg.ToString() |> logError
| Ok payload ->
"OK RESULT" |> logInfo
match payload |> box with
| :? seq<obj> as s ->
"IENUMERABLE" |> logInfo
s
|> Seq.iter innerSelect
| _ ->
"VALUE" |> logInfo
payload |> LogValueGeneric logInfo
|> ignore发布于 2020-06-26 19:56:27
将值与泛型类型进行模式匹配是很棘手的,因为编译器不会静态地知道seq<'a>中的'a应该是什么。针对seq<obj>的模式匹配也不起作用,因为例如seq<int>没有实现seq<obj>。
但是,对于集合,您是幸运的,因为泛型IEnumerable<'T>继承自非泛型IEnumerable,因此您可以使用它:
let print payload =
match box payload with
| :? System.Collections.IEnumerable as ie ->
let en = ie.GetEnumerator()
while en.MoveNext() do
printfn "ITEM: %A" en.Current
| v ->
printfn "VALUE: %A" v
print [1;2;3]
print "ABC"对于没有非泛型基类型的泛型类型,比如option<'T>,要让这样的东西工作起来比较困难,而且通常需要反射。
一个技巧是有一个通用的helper类,并使用反射将其指定为正确的类型,然后调用该方法(但通常,这非常难看):
type OptionPrinter<'T> =
static member Print(o:option<'T>) =
match o with
| None -> printfn "Nothing"
| Some v -> printfn "Something: %A" v
let print payload =
match box payload with
| :? System.Collections.IEnumerable as ie ->
let en = ie.GetEnumerator()
while en.MoveNext() do
printfn "ITEM: %A" en.Current
| null ->
printfn "NULL (or None)"
| v when v.GetType().IsGenericType &&
v.GetType().GetGenericTypeDefinition() = typedefof<option<_>> ->
let tya = v.GetType().GetGenericArguments()
let ty = typedefof<OptionPrinter<_>>.MakeGenericType(tya)
ty.GetMethod("Print").Invoke(null, [| v |]) |> ignore
| v ->
printfn "VALUE: %A" v
print [1;2;3]
print "ABC"
print (Some 10)
print None发布于 2020-06-27 05:58:53
作为对Tomas's answer的扩展注释:只要您愿意使用反射,您就可以直接调用泛型方法,而不依赖泛型类型。通过这种方式,我们也可以处理Result<_,_>类型区分的联合。
type TypePrinter =
static member PrintOption o =
match o with
| None -> printfn "Nothing"
| Some x -> printfn "Something: %A" x
static member PrintResult r =
match r with
| Error e-> printfn "Error: %A" e
| Ok x -> printfn "Ok: %A" x
let invokeGenericMethod methodName o =
typeof<TypePrinter>.GetMethod(methodName)
.MakeGenericMethod(o.GetType().GetGenericArguments())
.Invoke(null, [| o |]) |> ignore
let isOption o =
o.GetType().IsGenericType &&
o.GetType().GetGenericTypeDefinition() =
typedefof<Option<_>>
let isResult o =
o.GetType().IsGenericType &&
o.GetType().BaseType.GetGenericTypeDefinition() =
typedefof<Result<_,_>>
let print payload =
match box payload with
| :? System.Collections.IEnumerable as ie ->
for x in ie do
printfn "ITEM: %A" x
| null ->
printfn "NULL (or None)"
| v when isOption v ->
invokeGenericMethod "PrintOption" v
| v when isResult v ->
invokeGenericMethod "PrintResult" v
| v ->
printfn "VALUE: %A" v
print [1..3]
print "ABC"
print (Some 10)
print None
print (Ok 42)
print (Error "Oh no")https://stackoverflow.com/questions/62593837
复制相似问题