2010-06-15 94 views
7

這是我進入stackoverflow世界的第一步,所以如果我把任何東西搞砸了,我都很抱歉。使用IOperationBehavior提供一個WCF參數

我想創建一個WCF操作,它有一個參數不會暴露給外部世界,但會自動傳入函數。

因此,世界看到了這一點:int Add(int a, int b)

但它是這樣實現的:int Add(object context, int a, int b)

之後,上下文得到由系統在運行時提供。我正在使用的示例完全是人爲的,但它模仿了我在現實世界中正在研究的內容。

我能夠接近,但不是那麼完整。

首先,我創建了一個簡單的方法並編寫了一個應用程序來確認它的工作原理。它的確如此。它返回一個+ b並將上下文作爲字符串寫入我的調試。好極了。

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

然後我寫了下面的代碼:

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; } 
    } 
} 

我的WCF操作現在看起來是這樣的:

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

我更新引用不再顯示 '語境' 參數,該參數正是我想要的。

問題是,當我運行代碼時,它會通過AllocateInputs,然後在WCF內容的某個地方拋出一個Index was outside the bounds of the Array.錯誤。

我試過其他的東西,我發現我可以成功地改變參數的類型並重命名它並讓我的代碼工作。但是當我刪除參數時,它就會崩潰。

任何人都可以給我一些想法如何讓這個工作(或者如果它可以完成)。

回答

5

嗯,我想到了我自己。 MessagePartDescription具有一個Index屬性。我只需要重新調整這些值。

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; 
    }