如何从字符串中获得有区别的联合用例? [英] How do I get a discriminated union case from a string?

查看:54
本文介绍了如何从字符串中获得有区别的联合用例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个已区分的联合,我想根据一个字符串(从JSON文件读取)选择一个案例.这很容易做到:

I have a discriminated union and I want to select a case based on a string (which is read from a JSON file). This is easy to do:

type MyDU = A | B
let str = "B"
let myDU : MyDU =
    match str with
    | "A" -> MyDU.A
    | "B" -> MyDU.B
    | _ -> failwith "whatever"
// val myDU : MyDU = B

但是,有时情况很多,这需要大量输入.

However, sometimes there are many cases, which would require a lot of typing.

Microsoft.FSharp.Reflection库允许我获取UnionCaseInfo 对象:

The Microsoft.FSharp.Reflection library allows me to get a UnionCaseInfo object:

open Microsoft.FSharp.Reflection
let myDUInfo : UnionCaseInfo =
    FSharpType.GetUnionCases(typeof<MyDU>)
    |> Array.find (fun x -> x.Name = str)
// val myDUInfo : UnionCaseInfo = MyDU.B

我想将myDUInfo转换为联合大小写,以便获得与上面依赖match的代码相同的结果,但不必键入与所有大小写相对应的字符串.

I would like to convert myDUInfo into a union case so as to get the same result as the code above relying on match, but without having to type the strings corresponding to all the cases.

这可能吗?

推荐答案

要实例化联合案例,请使用

To instantiate a union case, use the FSharpValue.MakeUnion method. Here is a function that will instantiate a union case given its name:

let instantiate<'t> name =
    Reflection.FSharpType.GetUnionCases( typeof<'t> )
    |> Seq.tryFind (fun uc -> uc.Name = name)
    |> Option.map (fun uc -> Reflection.FSharpValue.MakeUnion( uc, [||] ) :?> 't)

用法:

> type T = A | B | C    
> instantiate<T> "A"

val it : T option = Some A

注意:此函数假定但不保证并集大小写没有参数.如果给它提供一个带有参数的案例,它将崩溃:

NOTE: this function assumes, but does not make sure, that the union case has no arguments. If you give it a case with arguments, it will crash:

> type T = A of int | B | C
> instantiate<T> "A"

System.Reflection.TargetParameterCountException: Parameter count mismatch.
   at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at FSI_0002.instantiate@5.Invoke(UnionCaseInfo uc) in c:\o\a.fsx:line 5
   at Microsoft.FSharp.Core.OptionModule.Map[T,TResult](FSharpFunc`2 mapping, FSharpOption`1 option)
   at <StartupCode$FSI_0006>.$FSI_0006.main@()
Stopped due to error

我将解决此问题的方法留给读者作为练习(提示:使用 UnionCase.GetFields方法).

I leave resolution of this problem as an exercise for the reader (hint: use the UnionCase.GetFields method).

这篇关于如何从字符串中获得有区别的联合用例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆