reflection - 如何从字符串中获取有区别的联合案例?

标签 reflection f# discriminated-union

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

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

但是,有时会有很多情况,需要大量打字。
Microsoft.FSharp.Reflection图书馆让我得到一个 UnionCaseInfo 目的:
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 的代码相同的结果,但不必键入与所有情况对应的字符串。

这可能吗?

最佳答案

要实例化联合案例,请使用 FSharpValue.MakeUnion method .这是一个函数,它将根据其名称实例化联合案例:

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

注意:此函数假定但不确保联合案例没有参数。如果你给它一个带参数的案例,它会崩溃:
> 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 method)。

关于reflection - 如何从字符串中获取有区别的联合案例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46334181/

相关文章:

typescript - TypeScript 可以通过 "extracted" bool 逻辑推断可区分联合的类型吗?

Java 反射 : How to get methods with no parameters only

java - 匿名类、私有(private)方法和反射

c# - 无法找到或加载程序集“tmpAssembly,

asynchronous - F# 是否有 Async.Sequential 来匹配 Async.Parallel?

f# - 是否可以将有区别的联合标签作为参数传递?

.net - 打印受歧视联盟的案例标识符

c# - 在 C# 中传递的参数不能正常工作?内部函数使用了反射

asynchronous - 有没有办法让F#中的异步工作流自动流水线?

azure - 为 Azure Function 编译 F# .NET Core 项目