In Part 1 of this series, I briefly explained what a Type Provider was and some of the main concepts which you would need to know. In Part 2, I am going to build a very simple Type Provider. The purpose of Part 2 is to cover the basics of developing Type Providers, how to test them with F# Interactive, and the support tools which make developing Type Providers easy.
I will make a Type Provider which generates a single type named “Hello”. At first it will just have a static property which returns the string
"World". Then I will add a static method which takes no parameters. Finally, I will add a static method which takes a parameter.
I start by creating a new F# Library Project and name it “TypeProviderTutorial”:
I then download the ProvidedTypes-0.4.fs file from the F# 3.0 Sample Pack and add that to my project:
Now it’s time to create our Type Provider. Add a new F# source code file beneath the “ProvidedTypes-0.4.fs” and name it “HelloWorld.fs”.
We’ll build up from the very bare minimum needed for a Type Provider. Starting with the boilerplate code which actually tells the compiler our type is a Type Provider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
This code will compile, but won’t do anything fun yet :).
[<TypeProvider>]this attribute tells the compiler that my type
HelloWorldTypeProvideris a Type Provider.
HelloWorldTypeProviderwe will put the code which actually generates new types.
[<assembly:TypeProviderAssembly]>this attribute indicates that this assembly contains a Type Provider.
With the skeleton in place, it’s time to start adding a little muscle. The following code will create a type named
Hello. This type won’t do anything because there are no members (static or instance). The code tells the type what assembly it belongs to, what namespace it is in, and the name of the type.
1 2 3 4 5 6 7 8 9 10 11 12 13
- I added the method
CreateTypewhich will return a new provided type when called. Right now, all this method does is create the most boring type ever.
typesis a list of types which the Type Provider generates
do this.AddNamespace(namespaceName, types)adds the generated types to the namespace
namespaceNameso that they can be used by a developer.
Build the library. When the build is complete, right click on the project in the Solution Explorer and choose “Send Project Output To F# Interactive”:
In F# Interactive run:
When you run
Tutorial.Hello you’ll get an error about not having a constructor. This is a good thing. The compiler can find the type, but there’s no constructor so it bombs out.
** Before Proceeding make sure to reset F# Interactive ** Do this by right clicking on the FSI window and choosing the reset option.
Adding a Static Property
Time to make that
Hello type actually do something. We’ll add a static property to this type called
StaticProperty which will return the string “World!”. Once we’ve added that, we’ll be able to write
Tutorial.Hello.World in our code and it will compile!
To add the static property, I’m going to update the
CreateType() method. It will create a static property by using the
ProvidedProperty type, then that value will be added as a member to the generated type.
Here’s the code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
- The function
ProvidedPropertyis the most important piece in this step. It creates a Property member which can then be added to our generated type.
t.AddMember staticPropwe add the Static Property we created to our type
staticProp.AddXmlDocDelayedjust adds Intellisense documentation for this property. You’ll see this text if you over your mouse over
Build and send our Library to F# Interactive then open the “Tutorial” namespace. Try executing
Tutorial.Hello.StaticProperty and see what you get. It should be
val it : string = "World!". Which is awesome! We now have a generated type which actually does something!
Adding a Static Method
Finally, we’ll add a static method to our
Hello type. To keep things consistent, this method will also return “World!”.
Again, the work will be done by updating
CreateType(). In this case, we’ll add a ProvidedMethod to our
Hello type. In the code sample below, I left out the StaticProperty to keep the code snippet small:
1 2 3 4 5 6 7 8
There isn’t much which is different between adding a static method and a static property. We use a different type:
ProvidedMethod. Also note that to make this static we set the
IsStaticMethod property to
true rather than the
InvokeCode is the function which will be executed when this method is called. In our case, it will just return “World!”.
Tutorial.Hello.StaticMethod();; and see what you get :).