zoukankan      html  css  js  c++  java
  • F#3.0新功能TypeProvider —— 定义自己的TP

    关于F#3.0的新功能Type provider,微软为我们提供了内置的6种type providers,用来处理不同数据存储结构.但是有些情况这些内置的方法并不能满足需求,因此就需要用户自己定义适合自己需求的TP。

    那么在自定义TP前,应该要考虑是不是真的需要自定义TP:

    1.   是否有一不受程序逻辑影响,不经常变动的schema(比如数据库由表、记录、字段、索引等组成)
    2.   是否经常需要使用到此TP
    3.   当程序运行时,此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

  • 相关阅读:
    git提交代码到github步骤
    HTML前端标签
    16-类视图
    15-auth系统与类视图
    14-中间件和上下文处理器
    13-会话技术及表单(cookies和session)
    07-Python Django view 两种return 方法
    10-请求与响应和HTML中的from表单
    09-表关联对象及多表查询
    08-常用查询及表关系的实现
  • 原文地址:https://www.cnblogs.com/FsharpZack/p/2775160.html
Copyright © 2011-2022 走看看