PhilBrown
PhilBrown

Reputation: 2999

f# types' properties in inconsistent order and of slightly differing types

I'm trying to iterate through an array of objects and recursively print out each objects properties.
Here is my object model:

type firmIdentifier = {
    firmId: int ;
    firmName: string ;
}
type authorIdentifier = {
    authorId: int ;
    authorName: string ;
    firm: firmIdentifier ;
}

type denormalizedSuggestedTradeRecommendations = {
    id: int ; 
    ticker: string ;
    direction: string ;
    author: authorIdentifier ;
}

Here is how I am instantiating my objects:

let getMyIdeasIdeas = [|
     {id=1; ticker="msfqt"; direction="buy"; 
        author={authorId=0; authorName="john Smith"; firm={firmId=12; firmName="Firm1"}};};

     {id=2; ticker="goog"; direction="sell"; 
        author={authorId=1; authorName="Bill Jones"; firm={firmId=13; firmName="ABC Financial"}};};

     {id=3; ticker="DFHF"; direction="buy"; 
        author={authorId=2; authorName="Ron James"; firm={firmId=2; firmName="DEFFirm"}};}|]

And here is my algorithm to iterate, recurse and print:

let rec recurseObj  (sb : StringBuilder) o=
            let props : PropertyInfo [] = o.GetType().GetProperties()
            sb.Append( o.GetType().ToString()) |> ignore
            for x in props do
                let getMethod = x.GetGetMethod()
                let value = getMethod.Invoke(o, Array.empty)
                ignore <|
                        match value with
                        | :? float  | :? int | :? string | :? bool as f -> sb.Append(x.Name + ": " + f.ToString() + "," ) |> ignore
                        | _ ->  recurseObj  sb value
 for x in getMyIdeas do
                recurseObj sb x
                sb.Append("\r\n") |> ignore

If you couldnt tell, I'm trying to create a csv file and am printing out the types for debugging purposes. The problem is, the first element comes through in the order you'd expect, but all subsequent elements come through with a slightly different (and confusing) ordering of the "child" properties like so:

RpcMethods+denormalizedSuggestedTradeRecommendationsid: 1,ticker: msfqt,direction: buy,RpcMethods+authorIdentifierauthorId: 0,authorName: john Smith,RpcMethods+firmIdentifierfirmId: 12,firmName: Firm1,

RpcMethods+denormalizedSuggestedTradeRecommendationsid: 2,ticker: goog,direction: sell,RpcMethods+authorIdentifierauthorName: Bill Jones,RpcMethods+firmIdentifierfirmName: ABC Financial,firmId: 13,authorId: 1,

RpcMethods+denormalizedSuggestedTradeRecommendationsid: 3,ticker: DFHF,direction: buy,RpcMethods+authorIdentifierauthorName: Ron James,RpcMethods+firmIdentifierfirmName: DEFFirm,firmId: 2,authorId: 2,

Any idea what is going on here?

Upvotes: 0

Views: 128

Answers (2)

PhilBrown
PhilBrown

Reputation: 2999

This is a reflection thing. You can't rely on the order of the properties using reflection. I need to sort using MetaTokens. I will post this solution when I get around to implementing it.

Upvotes: 0

Brian
Brian

Reputation: 118865

Does adding this help?

        for x in props |> Array.sortBy (fun p -> p.Name) do 
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In general, I think reflection returns entities (like attributes, methods, properties) in an unspecified order. So just pick a fixed sort order?

(Or did I misunderstand the issue?)

Upvotes: 1

Related Questions