Reputation: 877
Is there any way one can access the type attribute by using it's name represented in a string
. Something along the lines of:
type B = {FirstName:string; LastName:string}
let b = { FirstName="Bob"; LastName="Smith" }
b.``"FirstName"``
The reason being that I want to access the type dynamically based on the xml
based map.
Upvotes: 3
Views: 555
Reputation: 13577
This is something you can do via reflection. In addition to the general .NET reflection API, F# comes with a small reflection library, Microsoft.FSharp.Reflection
, that provides some utility functions for constructing and decomposing basic F# types like records.
You can get PropertyInfos
of all the record fields using:
FSharpType.GetRecordFields(typeof<B>)
Then you can decompose a record into an array of values and put them back into a record like this:
let fields = FSharpValue.GetRecordFields(b)
let b' = FSharpValue.MakeRecord(typeof<B>, fields) :?> B
You can build your own persistence library on top of that, but this is for the most part a solved problem. I think Json.NET should handle serializing records out of the box now, for sure there's an xml equivalent as well.
F# also offers a distinct alternative in the form of type providers. If you want your xmls to "drive" how your types look - particularly if you're accessing external sources that communicate through xml - you may want to look into FSharp.Data
and XmlProvider
. They give a very similar vibe to what you're doing in your example - you point the type provider to an xml sample and it generates a type corresponding to the xml's structure during the compilation. So you can just use the xml node names as regular field names in F# code, in a statically typed fashion.
Type providers are good for scripting and exploratory programming, since they save you time having to declare and update type definitions. But when building a more long-lasting application, you may find it desirable to use explicitly defined types as the representation.
Upvotes: 5