Type.GetType() 不适用于 C# 代码中的 F# 类型

Type.GetType() not working for F# type in C# code

我有一个名为 Assembly1 的 F# 程序集

我有以下模块:

namespace Assembly1

module MyModule =
   type MyClass(x: int, y: int) =
   new() = MyClass(0, 0)

在引用此 F# 程序集的 C# 程序集中,以下代码返回 'null' 的值:

var myType = Type.GetType("Assembly1.MyModule.MyClass, Assembly1");

我想做的是不可能的吗?

由于您已将 MyClass 放入模块中,因此它被编译为嵌套的 class。它的名字是 Assembly1.MyModule+MyClass.

在 C# 中,您应该能够像这样加载它:

var myType = Type.GetType("Assembly1.MyModule+MyClass, Assembly1");

如果您不想嵌套 classes(这在 C# 中通常不受欢迎),您可以直接在命名空间中定义它:

namespace Assembly1.LibraryXyz

type MyClass(x: int, y: int) = class end

这个 class 的名称将是 Assembly1.LibraryXyz.MyClass

要补充 ,还值得注意的是,F# 中的许多模块在 IL(因此在非 F# 语言)中使用的名称与它们在 F# 本身中的名称不同。

比如这段代码:

open System
open System.Reflection
open Microsoft.FSharp.Reflection

let private core =
    AppDomain.CurrentDomain.GetAssemblies()
    |> Seq.find (fun a -> a.GetName().Name = "FSharp.Core")

let private seqMod =
    core.GetTypes()
    |> Seq.filter FSharpType.IsModule
    |> Seq.find (fun t -> 
                   t.FullName = "Microsoft.FSharp.Collections.SeqModule")

会在FSharp.Core中找到Seq模块。

FSharp.Reflection 命名空间有一堆辅助方法,可以让 System.Reflection 使用 F# 特定类型的工作稍微轻松一些,因此值得在 FSI 中加载几个程序集并拥有如果您要使用 F# 代码进行大量反思工作,可以尝试一下。

您可以使用 CompiledName 属性自己创建具有 "mismatching" 名称的模块 - 这对于您需要同名类型和模块的情况特别有用。通常的约定(如 Seq type/module 所示)是用编译名称注释模块。

[<CompiledName("MyTypeModule")>]
module MyType =
    let getString m =
        match m with
        | MyType s -> s