F#3.0新功能TypeProvider —— 定义自己的TP
关于F#3.0的新功能Type provider,微软为我们提供了内置的6种type providers,用来处理不同数据存储结构.但是有些情况这些内置的方法并不能满足需求,因此就需要用户自己定义适合自己需求的TP。
那么在自定义TP前,应该要考虑是不是真的需要自定义TP:
- 是否有一不受程序逻辑影响,不经常变动的schema(比如数据库由表、记录、字段、索引等组成)
- 是否经常需要使用到此TP
- 当程序运行时,此schema是否经常变动
Ok,在定义自己的TP前,需要去F# sample pack中下载两个源文件:SampleProviders -> Shared,然后在你的F#库文件中将其加入,效果如下:
其中.fsi文件就相当于一个C#中的Interface, ProvidedTypes-head.fs就是那个.fsi文件的具体实现。
namespace Zack.Fsharp.MyTP open System open Samples.FSharp.ProvidedTypes open Microsoft.FSharp.Core.CompilerServices open Microsoft.FSharp.Quotations open System.Reflection [<TypeProvider>] type MyTP() as this = class //此基类位于head.fs文件中 inherit TypeProviderForNamespaces() //这个np(namespace)将包含此TP中定义的所有类和方法 let np = "Zack.Fsharp.TypeProviders" //获取当前运行程序集 let asm = System.Reflection.Assembly.GetExecutingAssembly() let baseType = Some typeof<string> //定义类tys,并将此类在上面定义的np中的名字定义为ZackDfd,将此类放入asm程序集 let tys = ProvidedTypeDefinition(asm,np,"ZackDfd",baseType) //定义一个构造函数 let ctor = ProvidedConstructor( parameters = [], //此处的InvokeCode为一个匿名函数,函数体为一个Quotation表达式,这里默认的构造函数设为基类的构造函数 InvokeCode = fun arg -> <@@ () @@>) //自定义一个函数 let dfnmethod = ProvidedMethod( //函数名 methodName = "Say", //此函数接受的参数列表,此例中只接受一个string类型的参数,参数相当于 Say(sA : string) parameters = [ProvidedParameter("sA",typeof<System.String>)], //函数返回值类型 returnType = typeof<obj>, //函数体为一个Quotation表达式,其中%%args.[1]即为参数列表中的第一个,当然,此例只有一个参数,而args.[0]这表示调用此方法的实例 InvokeCode =(fun args -> <@@ "Hi:" + ( %%args.[1] : System.String) @@>) ) //将刚才定义的构造函数付给类tys do tys.AddMember ctor //将方法加入类中 do tys.AddMember dfnmethod //将类加到命名空间 do this.AddNamespace(np,[tys]) end [<assembly:TypeProviderAssembly>] do()
编译好此库,接下来就是测试一下,新建一个Script文件,如下:
向Test.fsx中加入代码:
#r @"C:\Users\ZSH\Documents\Visual Studio 2012\Projects\MyTP\MyTP\bin\Debug\MyTP.dll" type T = Zack.Fsharp.TypeProviders.ZackDfd let c = new T() let str = c.Say("asdf")
上面的#r后面路径需要自己改一下,或者用.\bin....这样的,但是需要此脚本文件的位置与Bin同级
Ok,下面是测试结果(选中全部脚本中的代码,按 alt+enter):
type T = Zack.Fsharp.TypeProviders.ZackDfd
val c : T = null
val str : obj = "Hi:asdf"
Ok ,最初级阶段搞定,接下来还有很多要做的:),才能真正成为一个可用的TP。
接下来 将写些关于Quotation Expression 和更深入的TP内容。
如果你想看英文资料:http://msdn.microsoft.com/en-us/library/hh361034.aspx