lundi 27 février 2023

How do I get 'T from seq<'T> from a PropertyInfo array

I'm using reflection to try and create a datatable based on a record type. This works fine for a simple record type, but some of my records have sub records (also fine, just made the function recursive), or lists of sub records which is where I have my problem.

As an example, if i have the following types-

type ExampleSubType =
    {   PropertyA: string
        PropertyB: int }

type ExampleType =
    {   ID: int
        Name: string
        Example1: ExampleSubType list }

I'd like to create a data table with the following columns/types in this order-

ID: int
Name: string
PropertyA: string
PropertyB: int

I can already do this if I don't have a seq/arr/list anywhere in the types, but the ExampleSubType list part is throwing me off.

Here's the code I've got so far-


    let rec private createDataTableColumns record (propertyArr: PropertyInfo []) (dataTable: DataTable)  =
        propertyArr
        |> Seq.iteri(fun i property -> 
            let propType = property.GetType()
            let propValue = propertyArr.[i].GetValue(record)

            match FSharpType.IsRecord(propType), propValue with 
            | true, _ ->
                let subRecordType = propValue.GetType()
                let subPropertyArr = FSharpType.GetRecordFields (subRecordType)
                createDataTableColumns propValue subPropertyArr dataTable

            | false, :? seq<'T> as (_,test) -> 
                let subRecordType = test.GetType()
                let subPropertyArr = FSharpType.GetRecordFields (subRecordType)
                createDataTableColumns propValue subPropertyArr dataTable

            | _, _ ->
                dataTable.Columns.Add(property.Name, property.PropertyType) |> ignore
            )

The second match case is the issue. I can get it to match on that correctly but I'd like subRecordType to be typeof<'T>.

As it currently is, test.GetType() will return seq<'T>, not 'T and I don't know how to extract it from there.

I've also tried let subRecordType = typeof<'T>, which works elsewhere in my code, but here it will just return System.Object, not whatever type 'T is and i'm not sure why.





Aucun commentaire:

Enregistrer un commentaire