2012-04-14 38 views
3

我已經寫了叫RequestWrapper此類一個簡單的對象,它包含類型的一個方法:實施RequestWrapper此類REST風格的WCF服務

TResult WrapRequest<TResult>(Func<TResult> action) 

它封裝了try..catch任何行動,錯誤處理,日誌記錄,數據庫連接,事務(提交&回滾)等

目前我使用這樣的:(例如,不生產代碼)

return RequestWrapper.WrapRequest(() => 
{ 
    Topic entity = GetRepository<Topic>().Find(uid); 

    if (entity == null) 
     throw new EntityNotFoundException("Topic not found."); 

    return new Topic 
    { 
     Name = entity.Name, 
     Posts = entity.Posts.Select(x => new Post 
     { 
      Body = x.Body, 
     }).ToList() 
    }; 
}); 

我只是環繞我的REST風格的Web服務的每個方法(使用WCF和WebHttpBinding)。

我的問題是:我應該如何實現自動執行包裝的行爲?這可能嗎?

回答

4

您可以使用自定義IOperationInvoker,它包裝原來的一個做你所需要的。下面的代碼顯示了一個示例實現,您可以在http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/17/wcf-extensibility-ioperationinvoker.aspx找到更多關於invokers的信息。

public class StackOverflow_10156890 
{ 
    [ServiceContract] 
    public interface ITest 
    { 
     [WebGet] 
     [WrappedOperationBehavior] 
     string Echo(string text); 
     [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)] 
     [WrappedOperationBehavior] 
     int Divide(int x, int y); 
    } 
    public class Service : ITest 
    { 
     public string Echo(string text) 
     { 
      return text; 
     } 
     public int Divide(int x, int y) 
     { 
      return x/y; 
     } 
    } 
    class RequestWrapperOperationInvoker : IOperationInvoker 
    { 
     IOperationInvoker originalInvoker; 

     public RequestWrapperOperationInvoker(IOperationInvoker originalInvoker) 
     { 
      this.originalInvoker = originalInvoker; 
     } 

     public object[] AllocateInputs() 
     { 
      return this.originalInvoker.AllocateInputs(); 
     } 

     public object Invoke(object instance, object[] inputs, out object[] outputs) 
     { 
      Console.WriteLine("Do initialization, etc. here"); 
      object result = null; 
      try 
      { 
       result = this.originalInvoker.Invoke(instance, inputs, out outputs); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("Log exception: {0}: {1}", e.GetType().FullName, e.Message); 
       result = null; 
       outputs = null; 
      } 
      finally 
      { 
       Console.WriteLine("Do finalization, etc. here"); 
      } 

      return result; 
     } 

     public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) 
     { 
      throw new NotSupportedException("Only synchronous operations supported"); 
     } 

     public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) 
     { 
      throw new NotSupportedException("Only synchronous operations supported"); 
     } 

     public bool IsSynchronous 
     { 
      get { return true; } 
     } 
    } 
    class WrappedOperationBehaviorAttribute : Attribute, IOperationBehavior 
    { 
     public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 
     { 
     } 

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

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

     public void Validate(OperationDescription operationDescription) 
     { 
     } 
    } 
    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     var endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), ""); 
     endpoint.Behaviors.Add(new WebHttpBehavior()); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     WebClient c = new WebClient(); 
     Console.WriteLine(c.DownloadString(baseAddress + "/Echo?text=Hello%20world")); 

     c = new WebClient(); 
     c.Headers[HttpRequestHeader.ContentType] = "application/json"; 
     Console.WriteLine(c.UploadString(baseAddress + "/Divide", "{\"x\":12,\"y\":0}")); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
} 
+0

好的和完整的解決方案,非常感謝。 :) – 2012-04-24 21:56:42