Я изо всех сил пытаюсь вызвать метод (из библиотеки 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
Mark Pattison 16 Окт 2019 в 16:25

1 ответ

Лучший ответ

Вы можете изменить 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 без изменения passValueToCorrectMethod. В любом случае вы теряете безопасность времени компиляции.

2
CaringDev 17 Окт 2019 в 15:13