2013-08-07 4 views
10

Я реализую IErrorHandler, чтобы централизовать всю обработку ошибок для моей службы WCF в одном месте. Это работает довольно хорошо:Вкладные зависимости в реализацию IErrorHandler

public class ServiceErrorHandler : IErrorHandler 
{ 

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

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

} 

Теперь мы используем Ninject впрыснуть зависимости в остальной части сервиса, и я хотел бы сделать то же самое здесь. Так как WCF строит объекты, основанные на моей конфигурации, и я не думаю, что есть какие-то крючки в этот процесс, мне нужно использовать инъекции свойства:

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

Однако, это никогда не кажется, чтобы получить инъекции. Я попытался использовать расширения MVC от Ninject, чтобы установить ServiceErrorHandler, чтобы разрешить инъекцию, как фильтр, но это, похоже, не помогло. Есть ли способ сделать это?

+0

Вы тоже используете расширение Ninject WCF? –

+0

@ DanielMarbach: У меня есть расширения WCF, но я не вижу в них ничего, что могло бы помочь в этой ситуации. Есть ли что-то, что я мог бы использовать? – zimdanen

+0

@zimdanen Вы решили эту проблему? Лучше всего было бы вводить ILogger без IoC, но с чистым ... Pure DI. Просто добавьте интерфейс ILogger в свой 'ServiceErrorHandler' – Marshall

ответ

6

Поздний ответ, но вы можете вставлять зависимости в IErrorHandler, создавая свой собственный ServiceHost, скажем, TestServiceHost.

В вашей TestServiceHost вам нужно сделать:

  1. Реализовать конструктор с параметром IErrorHandler.
  2. Внутри создайте частный вложенный класс с именем ErrorHandlerBehaviour *, который должен реализовать как IServiceBehavior, так и IErrorHandler. Он также должен иметь конструктор с параметром IErrorHandler.
  3. Метод переопределения OnStarting(), в котором вы добавите ErrorHandlerBehaviour для обслуживания. Все действия должны быть добавлены до base.OnStarting().

* Идея взята из примера Юваля Лоуя в книге «Программирование служб WCF». Более подробную информацию о расширениях ошибок и ошибок вы можете найти там.

Вот приложение рабочего консольного хоста. Я не использую IoC там, только Pure DI, но вы можете легко решить регистратор с любой IoC вы хотите:

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

И конфигурация:

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

КСТАТИ. Удостоверьтесь, что вы добавили System.Runtime.Serialization к своим ссылкам

Смежные вопросы