gpt4 book ai didi

reflection - F# 反射 : Passing an Array as Argument to MethodInfo. 调用

转载 作者:行者123 更新时间:2023-12-01 12:04:20 27 4
gpt4 key购买 nike

previous post 中我看到了如何使用 F# 反射从 单个 盒装 Map 对象获取键,Map<'k,'v> ,在运行时。我试图扩展这个想法并传递一个 array 盒装 Map 对象,Map<'k,'v>[] ,但我找不到一种方法来扩展原始的单对象方法以将对象数组作为参数。我想出了一个可行但看起来不正确的解决方案。我正在寻找一种更好、更惯用的方式。

在下面的代码中,keysFromMap从单个盒装 Map<'k,'v> 中获取一组键争论; keysFromMapArray这是我第一次尝试用盒装 Map<'k,'v>[] 做同样的事情参数 - 但它不起作用 - 和 keysFromMapArrayWithCast确实有效,但必须在 FromMapArrayWithCast getter 级别进行向下转换似乎不正确。

我从运行 keysFromMapArray 得到的错误消息(test2 被注释掉):

{System.ArgumentException: Object of type 'System.Object[]' cannot be converted to type 'Microsoft.FSharp.Collections.FSharpMap`2[System.String,System.Int32][]'.

我的问题:为什么扩展 keysFromMap 方法以采用 map 参数数组不起作用,以及如何修复它以使其起作用?

示例代码:

module Example = 
open System

let foo1 = [| ("foo11", 11); ("foo12", 12) |] |> Map.ofArray
let foo2 = [| ("foo21", 21); ("foo22", 22) |] |> Map.ofArray

type KeyGetter =
static member FromMap<'K, 'V when 'K : comparison>(map:Map<'K, 'V>) =
[| for kvp in map -> kvp.Key |]

static member FromMapArray<'K, 'V when 'K : comparison>(maps:Map<'K, 'V>[]) =
maps |> Array.map (fun mp -> [| for kvp in mp -> kvp.Key |]) |> Array.concat

static member FromMapArrayWithCast<'K, 'V when 'K : comparison>(omaps:obj[]) =
let typedmaps = [| for omp in omaps -> omp :?> Map<'K, 'V> |] // -- DOWNCASTING HERE --
typedmaps |> Array.map (fun mp -> [| for kvp in mp -> kvp.Key |]) |> Array.concat

let keysFromMap (oMap : obj) : obj[] =
let otype = oMap.GetType()
match otype.Name with
| "FSharpMap`2" ->
typeof<KeyGetter>.GetMethod("FromMap")
.MakeGenericMethod(otype.GetGenericArguments())
.Invoke(null, [| box oMap |]) :?> obj[]
| _ ->
Array.empty

let keysFromMapArray (oMaps : obj[]) : obj[] =
// skipped : tests to check that oMaps is not empty, and that all elements have the same type...
let otype = oMaps.[0].GetType()
match otype.Name with
| "FSharpMap`2" ->

typeof<KeyGetter>.GetMethod("FromMapArray")
.MakeGenericMethod(otype.GetGenericArguments())
.Invoke(null, [| box oMaps |]) :?> obj[] // -- FAILS HERE --
| _ ->
Array.empty

let keysFromMapArrayWithCast (oMaps : obj[]) : obj[] =
// skipped : tests to check that oMaps is not empty, and that all elements have the same type...
let otype = oMaps.[0].GetType()
match otype.Name with
| "FSharpMap`2" ->

typeof<KeyGetter>.GetMethod("FromMapArrayWithCast")
.MakeGenericMethod(otype.GetGenericArguments())
.Invoke(null, [| box oMaps |]) :?> obj[]
| _ ->
Array.empty

[<EntryPoint>]
let main argv =
printfn "#test1: keys from Map<'k,'v> - works"
let test = keysFromMap foo1

// printfn "#test2: keysFromArray from Map<'k,'v>[] - FAILS"
// let test = keysFromMapArray [| foo1; foo2 |]

printfn "#test3: keysFromArrayWithCast from obj[] - works"
let test = keysFromMapArrayWithCast [| foo1; foo2 |]

Console.ReadKey() |> ignore
0 // return exit code 0

最佳答案

这与以下情况相同:

> type K = static member F(x:int[]) = 3
let f x = typeof<K>.GetMethod("F").Invoke(null, [|(x:obj[])|])
f [|2; 3|];;
System.ArgumentException: Object of type 'System.Object[]' cannot be converted to type 'System.Int32[]'.
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at <StartupCode$FSI_0002>.$FSI_0002.main@()
Stopped due to error

使中间函数通用可以解决问题。

> type K = static member F(x:int[]) = 3
let f x = typeof<K>.GetMethod("F").Invoke(null, [|(x:'a[])|]) // unconstrained!
f [|2; 3|];;
type K =
class
static member F : x:int [] -> int
end
val f : x:'a [] -> obj
val it : obj = 3

这可以应用于 keysFromMapArray

    let keysFromMapArray (oMaps : 'a[]) : obj[] =

关于reflection - F# 反射 : Passing an Array as Argument to MethodInfo. 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59280965/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com