Как вызвать методы, перегруженные по типу параметра в F #? - PullRequest
1 голос
/ 16 октября 2019

Я пытаюсь вызвать метод (из библиотеки C #), который перегружен типом параметра, в соответствии с универсальным параметром

В следующем примере вместо этого я использовал класс F # с перегруженными методами,чтобы проиллюстрировать это. Ключевым является тот факт, что универсальный параметр может быть либо struct, либо ссылочным типом, и это может быть производный тип одного из соответствующих типов параметров (здесь я использовал StreamWriter, чтобы проиллюстрировать это).

open System.IO

type MyClass() =
    member this.Method(n: int) = sprintf "Integer %i" n
    member this.Method(s: string) = sprintf "String %s" s
    member this.Method(w: TextWriter) = sprintf "Some kind of text writer"

let passValueToCorrectMethod (c: MyClass) (value: 'a) : string =
    match value with
    | :? int as n -> c.Method(n) // ERROR: Runtime type tests are not allowed on some types
    | :? string as s -> c.Method(s)
    | :? TextWriter as w -> c.Method(w)

// what I want to be able to do with it
let c = MyClass()
let sw = new StreamWriter("C:\temp\blah")

let result1 = passValueToCorrectMethod c 5
let result2 = passValueToCorrectMethod c "hi"
let result3 = passValueToCorrectMethod c sw

1 Ответ

2 голосов
/ 17 октября 2019

Вы можете изменить value: 'a на value: obj (в соответствии с предложением @Charles Mager) и при желании добавить кейс для всех случаев: _ -> failwith "No overload". Или, если вы хотите использовать отражение:

let passValueToCorrectMethod (c: MyClass) (value: 'a) : string =
    let valueType = typeof<'a>
    let mi = c.GetType().GetMethod("Method", BindingFlags.Instance ||| BindingFlags.Public, null, [| valueType |], null)
    if isNull mi then
        failwithf "No overload for %s" valueType.Name
    else    
        mi.Invoke(c, [| value |]) |> string

// what you'll be able to do with it
let c = MyClass()
let sw = new StreamWriter(".\\temp.txt")

passValueToCorrectMethod c sw // Some kind of text writer
passValueToCorrectMethod c () // Runtime Exception: No overload for Unit

Таким образом, это работает при добавлении / удалении Method s без изменения на passValueToCorrectMethod. В любом случае вы теряете безопасность времени компиляции.

...