我在C#共享项目中试图找到FSharpValue.GetUnionFields
的PCL(Profile 259)等价物。
在对象浏览器中通过C#项目,我看到了
namespace Microsoft.FSharp.Reflection
{
[AutoOpen]
[CompilationMapping(SourceConstructFlags.Module)]
public static class FSharpReflectionExtensions
{
public static Tuple<UnionCaseInfo, object[]> FSharpValue.GetUnionFields.Static(object value, Type unionType, [OptionalArgument] FSharpOption<bool> allowAccessToPrivateRepresentation);
}
}
这似乎是我正在寻找的,但我无法(或不知道如何)从C#调用它。通过F#,如果我打开命名空间,我可以调用扩展名FSharpValue.GetUnionFields
。 FSharpValue.GetUnionFields
不能从c#PCL编译。我对F#没有经验,所以我可能只是缺少与F#相关的一些重要知识 - C#interop?
作为参考,这是我从F#pcl。
中看到的[<AutoOpen>]
module Microsoft.FSharp.Reflection.FSharpReflectionExtensions
open Microsoft.FSharp.Reflection
val GetUnionFields : value:obj * unionType:System.Type * ?allowAccessToPrivateRepresentation:bool -> UnionCaseInfo * obj []
Repro项目在这里: https://github.com/kennethito/StackOverflowReferences/tree/master/FSharpValue-GetUnionFields
答案 0 :(得分:2)
同样,这需要使用反射。因为它是一个PCL,所以它特别讨厌,因为在运行时加载的FSharp.Core的实际版本是重要的。
以下内容应该有效:
public static Tuple<UnionCaseInfo, object[]> TestIt()
{
var option = new FSharpOption<int>(123);
MethodInfo method;
try
{
// If "4.4.0.0" is loaded at runtime, get directly
var t = typeof(FSharpValue);
method = t.GetRuntimeMethods().First(mi => mi.Name == "GetUnionFields");
}
catch
{
var t = typeof(FSharpReflectionExtensions);
method = t.GetRuntimeMethods().First(mi => mi.Name == "FSharp.Value.GetUnionFields.Static");
}
return (Tuple<UnionCaseInfo, object[]>)method.Invoke(null, new object[] { option, option.GetType(), null });
}
这试图直接在类型上找到方法(如何在FSharp.Core 4.4中指定),然后回退到PCL结构(作为扩展方法)。
以下C#控制台应用程序显示它正常工作:
static void Main(string[] args)
{
Tuple<UnionCaseInfo, object[]> results = CsharpPortable.Test.TestIt();
var uci = results.Item1;
Console.WriteLine("{0}:", uci.Name);
foreach (var pi in uci.GetFields())
{
Console.WriteLine("Property: {0}", pi.Name);
}
Console.ReadKey();
}