首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提供的类型可以在引号中使用吗? TypeProvider调用是否出现在ReflectedDefinition函数中?

提供的类型可以在引号中使用吗? TypeProvider调用是否出现在ReflectedDefinition函数中?
EN

Stack Overflow用户
提问于 2015-11-07 00:11:00
回答 1查看 109关注 0票数 1

我希望生成一个带有静态函数的类型,然后在使用ReflectedDefinition属性成为引号的函数中使用它。在我看来,这是一种将某些内容转换为FSharp类型的方便方法,它使用FSharp来组合函数和类型的域,并将组合的代码返回到其本机形式,它得到了类型检查、VS intellisense、高级函数等的好处。为了开始工作,我有了这个类型提供程序,主要是复制>粘贴在各种文章中。

代码语言:javascript
复制
[<TypeProvider>]
type CSoundTypeProvider(config: TypeProviderConfig) as this = 

    inherit ProvidedTypes.TypeProviderForNamespaces()

    let namespaceName = "TestNamespace"
    let thisAssembly = Assembly.GetExecutingAssembly()

//    config.

    let intType = typeof<int>
    let providedParam = ProvidedTypes.ProvidedParameter("prm", intType)
    let providedFunction = ProvidedTypes.ProvidedMethod("TestMethod", [providedParam], intType, IsStaticMethod=true
                                    , InvokeCode = fun args -> 
                                                  // The 'args' parameter represents expressions that give us access to the 
                                                  // instance on which the method is invoked and other parameters (if there are more)
                                                  let instance = args.[0]
                                                  // Now we can return quotation representing a call to MethodInfo 'p' with 'instance'
                                                  instance)
    let csoundProvidedWrapper = ProvidedTypes.ProvidedTypeDefinition(thisAssembly, namespaceName, "TestType", None)
    do csoundProvidedWrapper.AddMember(providedFunction)
    do this.AddNamespace(namespaceName, [csoundProvidedWrapper])

并用这个反映的定义来测试它:

代码语言:javascript
复制
[<ReflectedDefinition>]
let myfn i j =
    let k = i * j
    let x = k + 2
    let f = TestNamespace.TestType.TestMethod k
    let ret = f + 2
    ret

我正在像下面这样解析反射的定义:

代码语言:javascript
复制
<@ myfn @> |> println

DerivedPatterns.MethodWithReflectedDefinition(n),是一个函数(从另一篇文章中复制),它具有许多用于解析引用的活动模式,比如Patterns.Call(None,Patterns.Call expList),它为我提供了所有代码的扩展树,除了提供的静态方法。我想做的事有可能吗?如果是这样的话,在这里我可能忽略了println函数中的活动模式:

代码语言:javascript
复制
let println expr =
    let rec print expr = match expr with
        | Patterns.Application(expr1, expr2) ->
            // Function application.
            print expr1
            printf " "
            print expr2
        | Patterns.Call(None, DerivedPatterns.MethodWithReflectedDefinition(n), expList) ->
            print n
        | Patterns.Call(exprOpt, methodInfo, exprList) ->
            // Method or module function call.
            match exprOpt with
            | Some expr -> print expr
            | None -> printf "%s" methodInfo.DeclaringType.Name
            printf ".%s(" methodInfo.Name
            if (exprList.IsEmpty) then printf ")" else
            print exprList.Head
            for expr in exprList.Tail do
                printf ","
                print expr
            printf ")"
        | DerivedPatterns.Int32(n) ->
            printf "%d" n
        | Patterns.Lambda(param, body) ->
            // Lambda expression.
            printf "fun (%s:%s) -> " param.Name (param.Type.ToString())
            print body
        | Patterns.Let(var, expr1, expr2) ->
            // Let binding.
            if (var.IsMutable) then
                printf "let mutable %s = " var.Name
            else
                printf "let %s = " var.Name
            print expr1
            printf " in "
            print expr2
        | Patterns.PropertyGet(_, propOrValInfo, _) ->
            printf "%s" propOrValInfo.Name
        | DerivedPatterns.String(str) ->
            printf "%s" str
        | Patterns.Value(value, typ) ->
            printf "%s" (value.ToString())
        | Patterns.Var(var) ->
            printf "%s" var.Name
        | _ -> printf "%s" (expr.ToString())
    print expr

如果我不能这样做,您会推荐什么方法来生成我可以在引号中使用的FSharp定义?我很大程度上受到了FunScript项目的影响,但我希望避免这样的步骤:似乎每个类型记录定义都必须编译成一个独立的DLL。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-07 21:59:35

大多数类型提供程序演示使用擦除的类型提供程序,这些提供程序不生成实际的.NET类型。当使用擦除类型提供程序时,生成的方法将被擦除并替换为在方法的InvokeCode中提供的代码。

假设您有一个方法Foo,它用"Foo"作为参数擦除someFunc

代码语言:javascript
复制
myObj.Foo()   ~>    someFunc(myObj, "Foo")

在引文中,您还将看到擦除的版本(在直接<@ .. @>ReflectedDefinition中):

代码语言:javascript
复制
<@ myObj.Foo() @>  ~> <@ someFunc(myObj, "Foo") @>

FunScript类型提供程序的工作方式是,它生成一些包含函数名的虚拟代码,这样它就可以生成相应的JavaScript。说你有:

代码语言:javascript
复制
<@ win.Alert(arg) @> ~> <@ invokeFunction("alert", win, arg) @>

要做同样的事情,您需要定义一个像invokeFunction这样的函数,并生成适当的InvokeCode。然后,您可以在生成的引号中查找对invokeFunction的调用,并在那里做任何需要做的特殊事情。很难看出你到底想要做什么,但这至少会给你指明正确的方向。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33577558

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档