首先,列表不能包含不同類型的元素。因此,methods
列表中的所有功能將具有完全相同的第一個參數。
不過沒關係,你可以在技術上得到解決,通過擦除的功能類型(即他們鑄造obj
):
let methods = [
(fun (param1: MyRecordType) ->()) :> obj
(fun (param1: AnotherType) ->()) :> obj
]
現在你已經擁有屬於自己的漂亮的obj list
,其中每一個元素其實是一個功能。除了在編譯時不知道的情況,因爲你已經將它們鑄造爲obj
。
現在,F#中的函數由類FSharpFunc<_,_>
表示。第一個通用參數是輸入,第二個輸出。所以,你可以只取第一個通用的說法,這就是你的答案:
let paramType = fn.GetType().GetGenericArguments().[0]
除了我還要把保障到位,以確保我通過了obj
實際上是一個功能:
let funcType = typeof<FSharpFunc<_,_>>.GetGenericTypeDefinition()
let getFunctionParamType fn =
let fnType = fn.GetType()
if fnType.IsGenericType &&
funcType.IsAssignableFrom (fnType.GetGenericTypeDefinition())
then
Some (fnType.GetGenericArguments().[0])
else
None
注:有必要使用funcType.IsAssignableFrom
(而不是僅僅與funcType =
比較),因爲有些功能可以作爲一個自定義類的衍生從實施10。
更新:作爲KVB指出評價,爲了更固溶體,可以使用FSharpType.GetFunctionElements
和FSharpType.IsFunction
功能,其基本上包住上述邏輯以更方便,F# - 友好方式:
let getFunctionParamType fn =
if FSharpType.IsFunction fn &&
let input, output = FSharpType.GetFunctionElements fn
Some input
else
None
要當心雖然:反射是一件棘手的事情,很容易出錯,容易發生沉默故障。從你的問題來看,你並不真正瞭解它是如何工作的,這是使用它的一個強烈的禁忌。也許如果你描述了你的首要問題,有人可以提供更好的解決方案。
像往常一樣,這裏真正的問題可能是您想實現的「更高」目標。根據這一點,這個細節可能是或可能不是必需的。正如@JohnPalmer所說,類型將全部相同,因爲'List'只允許具有相同類型的元素(在這種情況下,具有相同簽名的函數)。 – TeaDrivenDev
把它看作模式匹配,但我想返回匹配中的類型列表,以便我可以遍歷它們。該應用程序是一個簡單的消息總線。 –
難道不同的消息是一個聯合的一部分,然後有一個'消息 - >單元(或響應而不是單位,響應是可能的響應的另一個聯合)列表? – Sehnsucht