我想生成一個帶有靜態函數的類型,然後我可以在使用屬性反射定義的函數中使用該函數。在我看來,一種將某些東西轉換成FSharp類型的方便方法,使用FSharp組合功能和類型的域,並將組合的代碼吐回到它的本機形式,從而獲得了類型檢查,VS智能感知,高階函數等,試圖讓我開始有這種類型的供應商,這主要是受複製>從各種文章在報價中是否可以使用提供的類型 - TypeProvider調用是否出現在ReflectedDefinition函數中?
[<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])
而與此測試它粘貼反映定義:
[<ReflectedDefinition>]
let myfn i j =
let k = i * j
let x = k + 2
let f = TestNamespace.TestType.TestMethod k
let ret = f + 2
ret
我解析反映的定義如下:
<@ myfn @> |> println
的println是一個函數(來自另一篇文章複製),其具有許多有源圖案的像Patterns.Call解析報價(無,DerivedPatterns.MethodWithReflectedDefinition(N),expList),其爲我提供的所有代碼的experssion樹,除了提供的靜態方法。我試圖做甚至可能嗎?如果是這樣,有什麼積極的模式,我會從我這裏的println函數錯過:
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項目的影響,但是希望避免看起來每個Typescript定義必須被編譯到一個單獨的DLL中的步驟。
非常感謝您花時間解釋這一點。我沒有意識到** InvokeCode **定義非常重要。我只是試圖生成與類型提供程序的公共接口一樣深的類型,因此在我的示例中是愚蠢的代碼。根據這些信息,編寫一個類型提供程序對於我真正想要做的事情來說是矯枉過正的,這就是代碼生成界面。 –