用反射发现属性失败

Failure to discover property with reflection

以下面的最小示例为例:

type IMyInterface =
    interface
        abstract member Name: string with get
    end

let testInstance =
    { new IMyInterface with
        member _.Name = "Hello Word" }

我本来天真地期望对 testInstance.GetType().GetProperties() 的调用包含一个 PropertyInfo 元素对应于 Name.

但是,只返回一个空数组。

使用 testInstance.GetType().GetProperty("Name") 并没有更好的效果,因为它只是 returns 一个 <null> 对象。

更令人困惑的是,Visual Studio 2022 IntelliSense 将 Name 列为有效的 属性(如我所料)。

如何得到PropertyInfo对应Name属性?

在 F# 中,所有接口实现都是私有的。这意味着接口方法和属性不会作为实现的方法和属性出现 class.

在 C# 中,这有点不同:如果定义一个 public 成员恰好与接口成员匹配,则不必明确告诉编译器它是接口实现,编译器会自动为你映射到接口。

因此,例如,如果您这样写:

class MyClass : IMyInterface {
  public string Name { get; }
}

C# 编译器实际上会这样编译它:

class MyClass : IMyInterface {
  public string Name { get; }
  string IMyInterface.Name { get { return this.Name; } }
}

(好吧,不完全是这样,但你明白了)

但 F# 编译器不这样做。如果你想要一个class 属性 除了界面属性,你还得自己滚一个:

type MyClass() =
  member __.Name = "Hello Word"
  interface IMyInterface with
    member this.Name = this.Name

但如果你只想要接口 属性,你可以从接口类型中获取它:

let nameProp = typeof<IMyInterface>.GetProperty("Name")
let helloWorld = nameProp.GetValue testInstance

或者,如果事先不知道接口类型,也可以从对象类型中获取:

let intf = testInstance.GetType().GetInterfaces().[0]
let nameProp = intf.GetProperty("Name")
let helloWorld = nameProp.GetValue testInstance