Wie kann ich die Ausdrücke aus einer Liste in ein Zitat spleißen, wenn ich die Anzahl und Arten dieser Ausdrücke zur Entwurfszeit nicht kenne?F # Typ Provider-Entwicklung: Bei der Bereitstellung einer Methode, wie auf Parameter der Variablen Nummer und Typ zugreifen?
Unten habe ich den vollständigen Code für einen Typ Provider enthalten. (. Ich das Konzept ausgezogen habe nach unten um das Problem zu demonstrieren) tritt Mein Problem bei diesen Zeilen:
let func = ProvidedMethod((*...*), InvokeCode = fun args ->
<@@ let stringParts =
args
|> List.mapi (fun i arg ->
if paramTypes.[i] = typeof<int> then
sprintf "%i" (%%arg: int)...
Auf dem Lambda-Parameter arg
, erhalte ich folgende Fehlermeldung:
error FS0446: The variable 'arg' is bound in a quotation but is used as part of a spliced expression. This is not permitted since it may escape its scope.``
ich kann‘ Ich finde heraus, wie man Code schreibt, so dass ich die Parameterwerte "extrahiere", wenn die Zahlen und Typen der Werte zur Zeit des Providerdesigns nicht bekannt sind (obwohl sie zur Kompilierungszeit bekannt sind).
Als ich einen Parameters Existenz und Art zur Entwurfszeit nicht bekannt ist, kann ich dies tun:
printfn "%A" (%%args.[0]: int)
Aber ich kann nicht herausfinden, wie aus dem Expr list
Eingang zu einem obj list
bekommen innerhalb Das Zitat.
Hier ist die vollständige Typ Provider-Code:
[<TypeProvider>]
type SillyProviderDefinition(config: TypeProviderConfig) as self =
inherit TypeProviderForNamespaces()
let sillyType = ProvidedTypeDefinition(THIS_ASSEMBLY, NAMESPACE, "SillyProvider", Some typeof<obj>)
do sillyType.DefineStaticParameters([ProvidedStaticParameter("argTypes", typeof<string>)], fun typeName args ->
let retType = ProvidedTypeDefinition(typeName, Some typeof<obj>)
let paramTypes =
(args.[0] :?> string).Split([|'|'|])
|> Array.map (function
| "int" -> typeof<int>
| "string" -> typeof<string>
| x -> failwithf "Invalid argType %A. Only string or int permitted" x)
let parameters =
paramTypes
|> Array.mapi (fun i p -> ProvidedParameter(sprintf "arg%i" i, p))
|> Array.toList
let func = ProvidedMethod("Stringify", parameters, typeof<string>, IsStaticMethod = true, InvokeCode = fun args ->
<@@ let stringParts =
args
|> List.mapi (fun i arg ->
if paramTypes.[i] = typeof<int> then
sprintf "%i" (%%arg: int)
elif paramTypes.[i] = typeof<string> then
(%%arg: string)
else
failwith "Unexpected arg type")
//printfn "%A" (%%args.[0]: int)
String.Join("", stringParts) @@>)
do retType.AddMember func
do sillyType.AddMember retType
retType)
do self.AddNamespace(NAMESPACE, [sillyType])
Können Sie mir zeigen, wo dieser Code im Zusammenhang mit der Art Provider-Klasse geht?Ich habe versucht, es zu integrieren, und es kompiliert, aber ich habe die folgenden Fehler, wenn ich versucht, auszuführen: '' Fehler FS0193: Das Modul/Namespace '. $ Library1' von der Übersetzungseinheit 'TypeProviderPain' nicht enthält den Namespace, das Modul oder den Typ 'formatInt @ 47''' '' scripty.fsx (7,9): Fehler FS1109: Ein Verweis auf den Typ' . $ [email protected] 'im Assembly 'TypeProviderPain' wurde gefunden, aber der Typ konnte in dieser Assembly nicht gefunden werden'' –
Ich konnte diesen Laufzeitfehler eliminieren, indem ich "formatInt" und "formatString" in ihr eigenes Modul verschoben habe. Ich musste auch "String.concat" durch "String.Join" ersetzen, um einen ähnlichen Fehler zu vermeiden: '' Fehler FS0193: Das Modul/Namespace 'Microsoft.FSharp.Collections' von der Kompilierungseinheit 'FSharp.Core' enthielt nicht das Namensraum, Modul oder Typ 'StringModule'''. Nachdem ich diese Schritte unternommen hatte, war ich in der Lage, den Typ-Provider zu betreiben. –
Diese Art von Fehlern sind leider die üblichen Typ Provider Schmerzen ... Froh, dass Sie es zur Arbeit gebracht haben! –