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

F# 提供的类型是否可以在引号中使用?TypeProvider调用是否出现在ReflectedDefinition函数中?,f#,type-providers,quotations,F#,Type Providers,Quotations,我想生成一个带有静态函数的类型,然后我可以使用ReflectedDefinition属性在成为引号的函数中使用它。在我看来,这似乎是一种将某些内容转换为FSharp类型的便捷方法,使用FSharp组合函数和类型的域,并将组合的代码转换回其本机形式,因为它获得了类型检查、VS intellisense、高阶函数等的好处。为了尝试并开始使用,我有了这个类型提供程序,大量复制->从各种文章粘贴 [<TypeProvider>] type CSoundTypeProvider(config:

我想生成一个带有静态函数的类型,然后我可以使用ReflectedDefinition属性在成为引号的函数中使用它。在我看来,这似乎是一种将某些内容转换为FSharp类型的便捷方法,使用FSharp组合函数和类型的域,并将组合的代码转换回其本机形式,因为它获得了类型检查、VS intellisense、高阶函数等的好处。为了尝试并开始使用,我有了这个类型提供程序,大量复制->从各种文章粘贴

[<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])

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

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

假设您有一个方法
Foo
,该方法使用
“Foo”
作为参数擦除到
someFunc

myObj.Foo()   ~>    someFunc(myObj, "Foo")
在引号中,您还将看到删除的版本(在direct
ReflectedDefinition
中):

~>
FunScript类型提供程序的工作方式是,它生成一些包含函数名的伪代码,以便随后生成相应的JavaScript。假设你有:

<@ win.Alert(arg) @> ~> <@ invokeFunction("alert", win, arg) @>
~>

要做同样的事情,您需要定义一个类似
invokeFunction
的函数,并生成相应的
InvokeCode
。然后,您可以在生成的引号中查找对
invokeFunction
的调用,并在那里执行您需要执行的任何特殊操作。很难看出您到底想做什么,但这至少应该为您指明了正确的方向。

非常感谢您花时间解释这一点。我没有意识到InvokeCode定义如此重要。我只是尝试生成与类型提供程序的公共接口一样深的类型,因此在我的示例中生成了哑代码。根据这些信息,也许编写一个类型提供程序对于我真正想做的事情来说是过分的,那就是编码生成一个接口。
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
myObj.Foo()   ~>    someFunc(myObj, "Foo")
<@ myObj.Foo() @>  ~> <@ someFunc(myObj, "Foo") @>
<@ win.Alert(arg) @> ~> <@ invokeFunction("alert", win, arg) @>