2016-05-05 15 views
8

Come si fornisce correttamente il codice a in un provider di tipo generativo che farebbe l'equivalente di quanto segue?Metodo di chiamata corretta che fa riferimento all'istanza in ProvidedConstructor

Dato:

module Utils = 
    let someFun (s : string) (inst : obj) = 
      // Does something here... 
     () 

ho bisogno di avere il tipo generato in modo efficace fare:

type NewGeneratedType() as self = 
    inherit BaseType() 

    do 
     Utils.someFun "Foo" (box self) 

ho la chiamata al costruttore di base di lavoro, ma non so come tagliare correttamente l'istanza e ottenere la funzione chiamata:

let ctor = ProvidedConstructor([]) 
let ci = baseType.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, [| |], null) 
ctor.BaseConstructorCall <- fun args -> ci, args 

// I do not know how to properly call this to match the constructor above 
ctor.InvokeCode <- fun args -> <@@() @@> 

risposta

2

ho ottenuto questo lavoro attraverso:

ctor.InvokeCode <- 
    fun args -> 
     let this = Seq.head args 
     let boxed = Expr.Coerce(this, typeof<obj>) 
     <@@ Utils.someFun "Foo" %%(boxed) @@> 

Nota che cercare di muovere i primi due righe nella giunzione causato ogni sorta di errori, ma quando lo tiro fuori, funziona perfettamente.

1

@Reed Copsey, Sto pensando che è necessario chiamare il tuo o costruttore wn realtà:

supponendo che si NewGeneratedType è un tipo concreto è stato definito già

<@@ let this = (ctor.Invoke([||])) :> NewGeneratedType 
    Utils.someFun "foo" (box this) 
@@> 

Se NewGeneratedType non è definita, ma è anche un tipo fornito per sé, avrete bisogno di un Expr.Coerce:

<@@ let this = (ctor.Invoke([||])) 
    let thisTyped = %%Expr.Coerce(this, providedType) 
    Utils.someFun "foo" (box this) 
@@> 

non sono sicuro al 100% questa funzione, ma spero che questo ti porterà nel modo.

+0

Sfortunatamente, aggiungendo 'ctor.Invoke' riporta l'errore' ... ha riportato un errore: costante sconosciuta 'ProviderImplementation.ProvidedTypes.ProvidedConstructor' nel metodo generato' –

3

Sembra un "this" argument is passed in as the last argument to the ctor

Da lì la vostra funzione InvokeCode will get run e la citazione restituita tradotto. Quindi, penso che tutto ciò che serve è qualcosa di simile:

ctor.InvokeCode <- fun args -> <@@ let me = Seq.last args @@> 
+1

'questo' è sempre il primo. 'Xs |> List.append x' è uguale a' List.append x xs' e equeal a 'x :: xs' –

+0

Nota che il tentativo di utilizzare questo dà sempre un errore di tipo non corrispondente:' Tipo non corrispondente quando splicing espressione nella citazione letterale. Il tipo dell'albero dell'espressione inserito non corrisponde al tipo previsto dall'operazione di splicing. Previsto 'NewGeneratedType', ma ha ricevuto il tipo 'System.Object'. Considera l'annotazione del tipo con il tipo di espressione previsto, ... "Nulla di ciò che cerco sembra consentirmi di aggirare questo problema. –

+0

BTW - questo ha aiutato farmi lì - ha registrato ciò che è stato richiesto al http://stackoverflow.com/a/37172942/65358 Grazie @CAIndy –