Getting the ctor parameter of a F# type provider
-
Saturday, August 25, 2012 7:31 PM
Hi,
F# type provider allows to get the runtime ctor params in methods or properties as,
let prop = ProvidedProperty("Instance", typeof<string>, GetterCode = (fun args -> <@@ (%%(args.[0]) : obj) @@>))
Is it possible to get the ctor param object as a part of type provider itself? I'm trying to create a TypeProvider based on an existing object (which is passed in the ctor) and I have to use reflection to iterate the members to create the wrapper type using TP. Any suggestions welcome.
Thanks,
Fahad
Fahad
All Replies
-
Monday, August 27, 2012 7:28 PMModerator
It's not entirely clear to me what you're asking. First of all, what do you mean by "ctor params"? Your provided constructors can use arbitrary erased representations, which may or may not be directly related to the parameters that are passed to them. For instance, if you have a provided constructor taking a string, then the body could be something like:
<@@ (args.[0] : string).ToLower() @@>
Now it's not possible for any provided member to know exactly what was passed in the constructor, since the "this" argument to each member will be the constructor parameter converted to lowercase.
Could you describe your scenario in greater detail? In particular, I find it helpful to script what the type provider user's code ought to look like - could you supply some example code that you'd like the user to be able to write?
-
Tuesday, August 28, 2012 6:56 AM
I'm trying to wrap a F# record to generate a wrapper type which would implement INotifyPropertyChanged, so I can easily use the same F# records in my WPF project. So the idea I'm trying to do is to pass an instance of the F# record and using reflection generate a wrapper type and do get/set in the actual instance itself (I use [<CLIMutable>] on F# records). I dint go ahead anywhere from the 1st line of code,
[<TypeProvider>]
type NotifyingTypeProvider(config:TypeProviderConfig) as this=
inherit TypeProviderForNamespaces()
let nameSpace = "System.Windows"
let thisAssembly = Assembly.GetExecutingAssembly()
do
let t = ProvidedTypeDefinition(thisAssembly,nameSpace,"NotifyingType",Some(typeof<obj>))
t.AddXmlDocDelayed(fun() -> "Create a Notifying type from a F# record")
let ctor = ProvidedConstructor([ ProvidedParameter("type",typeof<obj>) ], InvokeCode = (fun args -> <@@ (%%(args.[0]) : obj) @@>))
ctor.AddXmlDocDelayed(fun() -> "Pass a F# record to wrap")One other way I checked with the RegExTypeProvider which allows passing a string type and creating a wrapper type, but in my use case I actually need to pass the "Type" itself so to reflect and have a constructor that will allow passing an object, something like
type recordT = NotifyingType<typeof<....>>
let k = recordT(record) // pass the original F# record
Any details / references on how to achieve this would be great help.
Thanks,
Fahad
Fahad
-
Tuesday, August 28, 2012 4:44 PMModerator
First of all, you sadly can't use types as static parameters to a type provider, so you can't do
type recordT = NotifyingType<typeof<...>>
You can use the type's full name instead:
type recordT = NotifyingType<"MyNamespace.MyType">
Your type provider can then look up the actual type using reflection.
Alternatively, you could reflect over every type in the referenced assemblies and create a new provided type for each F# record type you find:
type recordT = NotifyingType.MyNamespace.MyType
Note that in either case the type that you want to wrap must already exist (that is, be defined in a different assembly from where you invoke the type provider). This is a serious limitation, but it is fundamental (i.e. I don't think there are any feasible workarounds).
- Edited by Keith BattocchiMicrosoft Contingent Staff, Moderator Tuesday, August 28, 2012 4:44 PM

