2013-08-07 57 views
10

Tôi đang triển khai IErrorHandler để tập trung tất cả xử lý lỗi cho dịch vụ WCF của tôi ở một nơi. Điều này hoạt động khá tốt:Tiêm phụ thuộc vào việc triển khai IErrorHandler

public class ServiceErrorHandler : IErrorHandler 
{ 

    public bool HandleError(Exception error) 
    { 
     // ..Log.. 
    } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     // ..Provide fault.. 
    } 

} 

Bây giờ, chúng tôi đang sử dụng Ninject để tiêm phụ thuộc vào phần còn lại của dịch vụ và tôi muốn thực hiện tương tự tại đây. Kể từ WCF là xây dựng các đối tượng dựa trên cấu hình của tôi, và tôi không nghĩ rằng tôi có bất cứ móc vào quá trình này, tôi cần phải sử dụng tiêm bất động sản:

[Inject] 
    public ILoggingService Logger { get; set; } 

Tuy nhiên, điều này không bao giờ dường như bị tiêm. Tôi đã thử sử dụng phần mở rộng MVC của Ninject để đặt ServiceErrorHandler để cho phép tiêm như bộ lọc, nhưng điều đó dường như không thực hiện mẹo. Có cách nào để thực hiện điều này không?

+0

Bạn cũng có sử dụng tiện ích mở rộng WCF Ninject không? –

+0

@DanielMarbach: Tôi có phần mở rộng WCF, nhưng tôi không thấy bất cứ điều gì trong đó có thể giúp đỡ trong tình huống này. Có cái gì mà tôi có thể sử dụng? – zimdanen

+0

@zimdanen bạn đã giải quyết vấn đề này chưa? Tốt nhất là tiêm ILogger mà không có IoC, nhưng với tinh khiết ... Pure DI. Chỉ cần tiêm một giao diện ILogger trong 'ServiceErrorHandler' của bạn – Marshall

Trả lời

6

Câu trả lời trễ, nhưng bạn có thể tiêm phụ thuộc vào IErrorHandler bằng cách tạo tùy chỉnh ServiceHost, giả sử TestServiceHost.

Trong bạn TestServiceHost bạn cần làm:

  1. Thực hiện constructor với IErrorHandler tham số.
  2. Bên trong, tạo lớp lồng nhau riêng có tên ErrorHandlerBehaviour *, cần triển khai cả hai IServiceBehaviorIErrorHandler. Nó cũng phải có hàm tạo với tham số IErrorHandler.
  3. Ghi đè phương thức OnStarting(), nơi bạn sẽ thêm ErrorHandlerBehaviour vào hành vi dịch vụ. Tất cả hành vi phải được thêm trước base.OnStarting().

* ý tưởng đến từ ví dụ của Juval Lowy trong sách - "Lập trình WCF dịch vụ". Thông tin thêm về lỗi và tiện ích mở rộng lỗi mà bạn có thể tìm thấy ở đó.

Đây là ứng dụng bảng điều khiển máy chủ đang hoạt động. Tôi không sử dụng IoC đó, chỉ cần Pure DI, nhưng bạn có thể dễ dàng giải quyết logger với bất kỳ IoC bạn muốn:

using System; 
using System.Collections.ObjectModel; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 

namespace ConsoleHost 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var logger = new DummyLogger(); 
      var errorHandler = new TestErrorHandler(logger); 

      ServiceHost host = new TestServiceHost(errorHandler, typeof(TestService), new Uri("net.tcp://localhost:8002")); 
      host.Open(); 

      Console.WriteLine("Press enter to exit"); 
      Console.ReadKey(); 
     } 
    } 

    [ServiceContract] 
    public interface ITestService 
    { 
     [OperationContract] 
     string Test(int input); 
    } 

    public class TestService : ITestService 
    { 
     public string Test(int input) 
     { 
      throw new Exception("Test exception!"); 
     } 
    } 

    public class TestErrorHandler : IErrorHandler 
    { 
     private ILogger Logger { get; } 

     public TestErrorHandler(ILogger logger) 
     { 
      Logger = logger; 
     } 

     public bool HandleError(Exception error) 
     { 
      Logger.Log(error.Message); 
      return true; 
     } 

     public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
     { 
      FaultException fe = new FaultException(); 
      MessageFault message = fe.CreateMessageFault(); 
      fault = Message.CreateMessage(version, message, null); 
     } 
    } 

    public class TestServiceHost : ServiceHost 
    { 
     private readonly IErrorHandler errorHandler; 

     public TestServiceHost(IErrorHandler errorHandler, Type serviceType, params Uri[] baseAddresses) 
      : base(serviceType, baseAddresses) 
     { 
      this.errorHandler = errorHandler; 
     } 

     protected override void OnOpening() 
     { 
      Description.Behaviors.Add(new ErrorHandlerBehaviour(errorHandler)); 
      base.OnOpening(); 
     } 

     class ErrorHandlerBehaviour : IServiceBehavior, IErrorHandler 
     { 
      private readonly IErrorHandler errorHandler; 

      public ErrorHandlerBehaviour(IErrorHandler errorHandler) 
      { 
       this.errorHandler = errorHandler; 
      } 

      bool IErrorHandler.HandleError(Exception error) 
      { 
       return errorHandler.HandleError(error); 
      } 

      void IErrorHandler.ProvideFault(Exception error, MessageVersion version, ref Message fault) 
      { 
       errorHandler.ProvideFault(error, version, ref fault); 
      } 

      void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
      { 
       foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) 
       { 
        channelDispatcher.ErrorHandlers.Add(this); 
       } 
      } 

      void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
      { 
      } 

      void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
      { 
      } 
     } 
    } 

    // Dummy logger 
    public interface ILogger 
    { 
     void Log(string input); 
    } 

    public class DummyLogger : ILogger 
    { 
     public void Log(string input) => Console.WriteLine(input); 
    } 
} 

Và cấu hình:

<system.serviceModel> 
    <services> 
    <service name="ConsoleHost.TestService"> 
     <endpoint address="net.tcp://localhost:8002/TestService" 
       binding="netTcpBinding" 
       contract="ConsoleHost.ITestService" /> 
    </service> 
    </services> 
</system.serviceModel> 

Btw. Đảm bảo bạn đã thêm System.Runtime.Serialization vào tài liệu tham khảo