2010-06-15 10 views
7

Questo è il mio primo passo nel mondo dello stackoverflow, quindi scusate se prendo qualcosa.Utilizzo di IOperationBehavior per fornire un parametro WCF

Sto provando a creare un'operazione WCF che ha un parametro che non è esposto al mondo esterno, ma viene invece automaticamente passato alla funzione.

Così il mondo vede questo: int Add(int a, int b)

ma è implementato come: int Add(object context, int a, int b)

Poi, il contesto viene fornita dal sistema a run-time. L'esempio con cui sto lavorando è completamente artificiale, ma imita qualcosa che sto osservando in uno scenario del mondo reale.

Sono in grado di avvicinarmi, ma non del tutto lì.

Prima di tutto, ho creato un metodo semplice e ho scritto un'applicazione per confermare il suo funzionamento. Lo fa. Restituisce un + b e scrive il contesto come una stringa sul mio debug. Sìì.

[OperationContract] 
    int Add(object context, int a, int b); 

Ho poi scritto il seguente codice:

public class SupplyContextAttribute : Attribute, IOperationBehavior 
{ 
    public void Validate(OperationDescription operationDescription) 
    { 
     if (!operationDescription.Messages.Any(m => m.Body.Parts.First().Name == "context")) 
      throw new FaultException("Parameter 'context' is missing."); 
    } 

    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) 
    { 
     dispatchOperation.Invoker = new SupplyContextInvoker(dispatchOperation.Invoker); 
    } 

    public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) 
    { 
    } 

    public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 
    { 
     // Remove the 'context' parameter from the inbound message 
     operationDescription.Messages[0].Body.Parts.RemoveAt(0); 
    } 
} 

public class SupplyContextInvoker : IOperationInvoker 
{ 
    readonly IOperationInvoker _invoker; 

    public SupplyContextInvoker(IOperationInvoker invoker) 
    { 
     _invoker = invoker; 
    } 

    public object[] AllocateInputs() 
    { 
     return _invoker.AllocateInputs().Skip(1).ToArray(); 
    } 

    private object[] IntroduceContext(object[] inputs) 
    { 
     return new[] { "MyContext" }.Concat(inputs).ToArray(); 
    } 

    public object Invoke(object instance, object[] inputs, out object[] outputs) 
    { 
     return _invoker.Invoke(instance, IntroduceContext(inputs), out outputs); 
    } 

    public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) 
    { 
     return _invoker.InvokeBegin(instance, IntroduceContext(inputs), callback, state); 
    } 

    public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) 
    { 
     return _invoker.InvokeEnd(instance, out outputs, result); 
    } 

    public bool IsSynchronous 
    { 
     get { return _invoker.IsSynchronous; } 
    } 
} 

E la mia operazione WCF ora assomiglia a questo:

[OperationContract, SupplyContext] 
    int Amend(object context, int a, int b); 

I miei riferimenti aggiornati mostrano non è più il parametro 'contesto', che è esattamente quello che voglio.

Il problema è che quando eseguo il codice, supera AllocateInputs e poi genera un errore Index was outside the bounds of the Array. da qualche parte nell'intestino WCF.

Ho provato altre cose, e ho scoperto che posso cambiare con successo il tipo di parametro e rinominarlo e far funzionare il mio codice. Ma nel momento in cui rimuovo il parametro cade.

Qualcuno può darmi un'idea di come farlo funzionare (o se può essere fatto del tutto).

risposta

5

Beh, l'ho capito da solo. MessagePartDescription ha una proprietà Index. Ho solo bisogno di ridefinire questi valori.

public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 
    { 
     var parts = operationDescription.Messages[0].Body.Parts; 
     parts.RemoveAt(0); 
     for (int i = 0; i < parts.Count; i++) 
      parts[i].Index = i; 
    } 
Problemi correlati