F#:如何访问 Dotnet 对象方法的特定重载作为第一个 Class-对象
F#: How to Access a Dotnet Object's Method's Specific Overload as a First Class-object
我能做到(F# FSI):
let o = Object()
let m = o.GetHashCode;; //[1]
val o : Object
val m : (unit -> int)
这使得方法 GetHashCode
可作为绑定 m
:
中的第一个 class 函数访问和调用
m ();;
val it : int = 12345678
如果所讨论的方法存在重载,比如另一个 Object.GetHashCode(int whateverParameter)
,我将如何着手执行此操作?我现在只能得到 'first' (最短?)方法。我可以在调用 1 中提供额外的参数类型信息来指定我想要的重载吗?
编辑
感谢您到目前为止的投入。类型注释似乎是可行的方法。尽管如此,对于我更复杂的示例,我仍然无法弄清楚如何正确地做到这一点。
这是我正在处理的类型的具体方法签名(它来自 octokit.net 库,所以你需要在你的 fsi 中使用类似 #r "nuget:include=Octokit"
的东西 [with /langversion:preview
]).
我有兴趣检索 GetAllForRepository
的特定重载,顺便说一句,列出的第一个:GetAllForRepository(string, string)
.
open Octokit
let client = GitHubClient(...)
client.Issue.GetType().GetMethods()
|> Seq.filter (fun methodInfo -> methodInfo.Name.StartsWith("GetAllForRepository"))
|> Seq.map (fun methodInfo -> (methodInfo.GetParameters(), methodInfo.ReturnType))
|> Seq.map (fun (parameterInfos, returnType) ->
(parameterInfos |> Seq.map (fun parameterInfo -> parameterInfo.ParameterType.FullName), returnType.FullName))
val it : seq<seq<string> * string> =
seq
[(seq ["System.String"; "System.String"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.Int64"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.String"; "System.String"; "Octokit.ApiOptions"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.Int64"; "Octokit.ApiOptions"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.String"; "System.String"; "Octokit.RepositoryIssueRequest"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.Int64"; "Octokit.RepositoryIssueRequest"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq
["System.String"; "System.String"; "Octokit.RepositoryIssueRequest";
"Octokit.ApiOptions"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq
["System.Int64"; "Octokit.RepositoryIssueRequest";
"Octokit.ApiOptions"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]")]
现在,'shortest' 签名采用一个 int64
参数:
let m = client.Issue.GetAllForRepository;;
val m :
(int64 ->
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>)
我可以显式声明签名并接收相同的方法:
let m: (int64 -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
val m :
(int64 ->
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>)
但是访问 (string, string)
版本给我:
let m: (string -> string -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
let m: (string -> string -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
--------------------------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(33,117): error FS0193: Type constraint mismatch. The type
'string'
is not compatible with type
'int64'
尝试访问具有多个参数的任何其他重载时出现类似错误:
let m: (int64 -> Octokit.RepositoryIssueRequest -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
let m: (int64 -> Octokit.RepositoryIssueRequest -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
-------------------------------------------------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(37,140): error FS0001: This expression was expected to have type
'Octokit.RepositoryIssueRequest -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>'
but here has type
'System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>'
let m: (int64 -> Octokit.RepositoryIssueRequest -> Octokit.ApiOptions -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.- GetAllForRepository;;
let m: (int64 -> Octokit.RepositoryIssueRequest -> Octokit.ApiOptions -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
-----------------------------------------------------------------------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(36,162): error FS0001: This expression was expected to have type
'Octokit.RepositoryIssueRequest -> Octokit.ApiOptions -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>'
but here has type
'System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>'
那么,我是不是在类型注释方面做错了什么?
是的,类型注释将允许您select覆盖您想要的方法:
type MyClass() =
member __.MyMethod() = 1
member __.MyMethod(x : int) = 2
let o = MyClass()
let m1 : (unit -> int) = o.MyMethod
let m2 : (int -> int) = o.MyMethod
printfn "%A" <| m1 ()
printfn "%A" <| m2 0
根据您的编辑,该方法的输入是 string * string
,而不是 string -> string
(即未柯里化与柯里化),所以我认为这会起作用:
let m : (string * string -> _) = client.Issue.GetAllForRepository
我能做到(F# FSI):
let o = Object()
let m = o.GetHashCode;; //[1]
val o : Object
val m : (unit -> int)
这使得方法 GetHashCode
可作为绑定 m
:
m ();;
val it : int = 12345678
如果所讨论的方法存在重载,比如另一个 Object.GetHashCode(int whateverParameter)
,我将如何着手执行此操作?我现在只能得到 'first' (最短?)方法。我可以在调用 1 中提供额外的参数类型信息来指定我想要的重载吗?
编辑
感谢您到目前为止的投入。类型注释似乎是可行的方法。尽管如此,对于我更复杂的示例,我仍然无法弄清楚如何正确地做到这一点。
这是我正在处理的类型的具体方法签名(它来自 octokit.net 库,所以你需要在你的 fsi 中使用类似 #r "nuget:include=Octokit"
的东西 [with /langversion:preview
]).
我有兴趣检索 GetAllForRepository
的特定重载,顺便说一句,列出的第一个:GetAllForRepository(string, string)
.
open Octokit
let client = GitHubClient(...)
client.Issue.GetType().GetMethods()
|> Seq.filter (fun methodInfo -> methodInfo.Name.StartsWith("GetAllForRepository"))
|> Seq.map (fun methodInfo -> (methodInfo.GetParameters(), methodInfo.ReturnType))
|> Seq.map (fun (parameterInfos, returnType) ->
(parameterInfos |> Seq.map (fun parameterInfo -> parameterInfo.ParameterType.FullName), returnType.FullName))
val it : seq<seq<string> * string> =
seq
[(seq ["System.String"; "System.String"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.Int64"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.String"; "System.String"; "Octokit.ApiOptions"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.Int64"; "Octokit.ApiOptions"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.String"; "System.String"; "Octokit.RepositoryIssueRequest"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq ["System.Int64"; "Octokit.RepositoryIssueRequest"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq
["System.String"; "System.String"; "Octokit.RepositoryIssueRequest";
"Octokit.ApiOptions"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]");
(seq
["System.Int64"; "Octokit.RepositoryIssueRequest";
"Octokit.ApiOptions"],
"System.Threading.Tasks.Task`1[[System.Collections.Generic.IReadOnlyList`1[[Octokit.Issue, Octokit, Version=0.48.0.0, Culture=neutral, PublicKeyToken=null]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]")]
现在,'shortest' 签名采用一个 int64
参数:
let m = client.Issue.GetAllForRepository;;
val m :
(int64 ->
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>)
我可以显式声明签名并接收相同的方法:
let m: (int64 -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
val m :
(int64 ->
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>)
但是访问 (string, string)
版本给我:
let m: (string -> string -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
let m: (string -> string -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
--------------------------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(33,117): error FS0193: Type constraint mismatch. The type
'string'
is not compatible with type
'int64'
尝试访问具有多个参数的任何其他重载时出现类似错误:
let m: (int64 -> Octokit.RepositoryIssueRequest -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
let m: (int64 -> Octokit.RepositoryIssueRequest -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
-------------------------------------------------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(37,140): error FS0001: This expression was expected to have type
'Octokit.RepositoryIssueRequest -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>'
but here has type
'System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>'
let m: (int64 -> Octokit.RepositoryIssueRequest -> Octokit.ApiOptions -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.- GetAllForRepository;;
let m: (int64 -> Octokit.RepositoryIssueRequest -> Octokit.ApiOptions -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>) = client.Issue.GetAllForRepository;;
-----------------------------------------------------------------------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(36,162): error FS0001: This expression was expected to have type
'Octokit.RepositoryIssueRequest -> Octokit.ApiOptions -> System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>'
but here has type
'System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<Octokit.Issue>>'
那么,我是不是在类型注释方面做错了什么?
是的,类型注释将允许您select覆盖您想要的方法:
type MyClass() =
member __.MyMethod() = 1
member __.MyMethod(x : int) = 2
let o = MyClass()
let m1 : (unit -> int) = o.MyMethod
let m2 : (int -> int) = o.MyMethod
printfn "%A" <| m1 ()
printfn "%A" <| m2 0
根据您的编辑,该方法的输入是 string * string
,而不是 string -> string
(即未柯里化与柯里化),所以我认为这会起作用:
let m : (string * string -> _) = client.Issue.GetAllForRepository