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