.net F#转换为编译时未知的类型

.net F#转换为编译时未知的类型,.net,reflection,casting,f#,.net,Reflection,Casting,F#,如何铸造给定的obj列表 let l = [1. :> obj; 2. :> obj] 当编译时不知道原始类型(在本例中为float)时返回到float列表 我已经试过(表明我对此知之甚少:): 这是非常失败的 及 let castMe(ty:Type)(arr:obj列表)= 设m=typeof.GetMethod(“Cast”) 设m=m.MakeGenericMethod([| ty |]) m、 调用(null,[| arr |]):?>System.Collections

如何铸造给定的obj列表

let l = [1. :> obj; 2. :> obj]
当编译时不知道原始类型(在本例中为float)时返回到float列表

我已经试过(表明我对此知之甚少:):

这是非常失败的

let castMe(ty:Type)(arr:obj列表)=
设m=typeof.GetMethod(“Cast”)
设m=m.MakeGenericMethod([| ty |])
m、 调用(null,[| arr |]):?>System.Collections.Generic.IEnumerable
设t=(l |>List.head).GetType();
l|>castMe t;;
它失败于:

错误FS0030:值限制。已将值“it”推断为 具有泛型类型
valit:Generic.IEnumerable这个没有语法,因为正如韦斯利·怀瑟所指出的那样,对于这样一个表达式,你是无能为力的。但是,由于您处理的是
Expr
值,因此可以使用
Expr.concure
方法创建与所需内容等效的表达式树。

您可以使用通过反射调用的帮助器类执行最初要求的操作:

type CastHelper<'t>() =
    static member Go(xs : obj list) : 't list =
        xs |> List.map (fun x -> x :?> 't)

let castList (xs : obj list) : obj =

    let typ =
        match xs with
        | [] -> failwithf "Can't cast an empty list"
        | x::xs -> x.GetType()

    let doCast = typedefof<CastHelper<_>>.MakeGenericType([|typ|])
                                         .GetMethod("Go")

    doCast.Invoke(null, [|box xs|])
i、 e.结果的动态类型为
float list
(但静态类型为
obj
),而原始输入的动态类型为
obj list


为了有价值地使用结果,您需要一些关注区别的东西,但这样的代码肯定存在。

假设您可以转换为“运行时类型”,您打算如何处理这个值?不能使用
运算符调用方法或访问数据,因为该类型在运行时而不是编译时已知。是否要使用反射来调用值的方法或属性?如果是,没有理由强制转换它。我正在尝试创建F#type提供程序,它将从字典中提供类似F#type的内容,并将这些字典列表作为类型成员。@WesleyWiser(如果这完全无关,请让我知道Klark,我“删除它”)@RubenBartelink谢谢,这个问题的背景很有帮助。在我看来,您的类型提供程序只需要生成一个表示字典的类型。通读这些教程给我的印象是,您不需要像您试图做的那样强制转换到运行时。实现类型提供程序的哪一部分让您陷入困境?很好。但是,是否也可以获得浮点列表的静态类型?唯一的方法是通过反射,或者如果您特别想查找
浮点列表
,则通过显式类型测试-这是从动态类型到静态类型的两种方法。在
Go
中的
CastHelper
中,结果确实具有静态类型的
float list
,因此一个选项是使该方法更长,并让它执行您实际想要对列表执行的操作。谢谢,这非常有用。您能告诉我一些关于如何使用Expr.concure的资源吗?@Klark-作为一个例子,
Expr.concure(,typeof)
大致相当于
float@@@>
let castMe (ty : Type) (arr : obj list)  =
        let m = typeof<Enumerable>.GetMethod("Cast")
        let m = m.MakeGenericMethod([|ty|])
        m.Invoke(null, [|arr|]) :?> System.Collections.Generic.IEnumerable<_>

let t = (l |> List.head).GetType();
l |> castMe t;;
type public InnerData(query, table) =
    ...
    member __.Data = data       // map <string, obj list>
    member __.Headers = headers // Dictionary <string, Type>
ty.AddMember(ProvidedConstructor([], InvokeCode = fun [] -> <@@ InnerData(queryParam, tableNameParam) :> obj @@>))
do mdsTy.DefineStaticParameters([tableNameParam; queueryParam], fun tyName [| :? string as tableNameParam; :? string as queryParam |] ->
        let ty = ProvidedTypeDefinition(
                        asm, 
                        ns, 
                        tyName, 
                        baseType = Some(typeof<obj>))

        let mdsInner = MdsData(mdsQueryParam, tableNameParam)

        for header in mdsInner.Headers do
            let columnName = header.Key
            let columnType = header.Value

            let arrayType = typedefof<IEnumerable<_>>.MakeGenericType(typeof<obj>)
            // This works, but returns obj list. I would like to return a list of columnType that represents the downcasted version of arraytype.

            let property = ProvidedProperty(columnName, arrayType,
                                GetterCode = fun [innerType] -> <@@ ((%%innerType:obj) :?> InnerData).Data.[columnName] @@>)
            ty.AddMember(property)
type CastHelper<'t>() =
    static member Go(xs : obj list) : 't list =
        xs |> List.map (fun x -> x :?> 't)

let castList (xs : obj list) : obj =

    let typ =
        match xs with
        | [] -> failwithf "Can't cast an empty list"
        | x::xs -> x.GetType()

    let doCast = typedefof<CastHelper<_>>.MakeGenericType([|typ|])
                                         .GetMethod("Go")

    doCast.Invoke(null, [|box xs|])
> let xs = [1.0 :> obj ; 2.0 :> obj];;

val xs : obj list = [1.0; 2.0]

> let ys = castList xs;;

val ys : obj = [1.0; 2.0]

> xs.GetType().FullName;;

val it : string =
  "Microsoft.FSharp.Collections.FSharpList`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"

> ys.GetType().FullName;;

val it : string =
  "Microsoft.FSharp.Collections.FSharpList`1[[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"