Saturday, May 12, 2012

Type Provider - Share Information by giving a customized base class

I have a "bad" habit. It is not easy for me to say forget about, let it go. Last night this little monster came back haunted me again. Mostly likely I won't be able to solve the original problem, instead I would be lured into a new territory. Last night the monster reminded me the unit test type provider and led me to think how to share the information between different type provider methods.

The current type provider's method call is isolated, there is few sample about how to maintain a internal state. The regex type provider is a sample. Once you have the matched group, that group is a self-sustained structure and do not need to interactive with other match group. What I am interested is how to make the information flow/share between type provider's method call. For example, I want Method2 to retrieve the information sent in Method1. The b should be "aa"
type T = MyTypeProvider
let t = T()
let b = t.Method2()
The approach I am going to use is to use the base class in the type provider. Current sample type providers always take obj as base class, while I want to use my class to store my own stuff. You can download the code from here.

The base class used to hold the information passed in method1 is X. Please make sure the type and member  must be public.

type BaseType2() =
     member val X = "" with get, set
The generated code take the first element %%args.[0] as "this" pointer and converted to the BaseType2. You do not have to convert to obj first and then to BaseType2. That conversion will generate an error when you use the type provider.
InvokeCode = fun args -> <@@ (%%args.[0]:BaseType2).X <- (%%args.[1]) @@>)
The important is the constructor, please return a BaseType2(). Otherwise, a runtime error complains about NULL reference.  I guess that's everything you needs to get it working.

the testing program is:

#r @".\bin\Debug\ShareInfoSampleTypeProvider.dll"

type T = Samples.ShareInfo.TPTest.TPTestType
let t = T()
let a = t.F2()

printfn "the parameter in F1 is %A" a

and result should be:

the parameter in F1 is "aa"

This technique open a door to extend the existing types in a more automated way. You can use the extension method to extend the type, but you have to type each character. Now you can write your type provider to extend your types. Your program will generate the methods and properties.

Allow me some time to think about a good sample, now it is time to catch up some sleep.. :)

No comments: