将依赖项注入IErrorHandler实现

时间:2013-08-07 20:37:43

标签: wcf ninject ierrorhandler

我正在实现IErrorHandler,以便在一个地方集中我的WCF服务的所有错误处理。这很有效:

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

然而,这似乎永远不会被注入。我尝试使用Ninject的MVC扩展来设置ServiceErrorHandler以允许像过滤器一样注入,但这似乎没有成功。有没有办法让这种情况发生?

1 个答案:

答案 0 :(得分:6)

答案较晚,但您可以通过创建自定义jQuery('.mydiv').animate({ width:new_width, },1000); 将依赖关系注入IErrorHandler,让我们说ServiceHost

在你需要做的TestServiceHost中:

  1. 使用TestServiceHost参数实现构造函数。
  2. 在里面,创建一个名为IErrorHandler *的私有嵌套类,它需要同时实现ErrorHandlerBehaviourIServiceBehavior。它还必须具有带IErrorHandler参数的构造函数。
  3. 覆盖IErrorHandler方法,您可以在其中添加OnStarting()服务行为。必须在ErrorHandlerBehaviour之前添加所有行为。
  4. *这个想法来自Juval Lowy在书中的例子 - "编程WCF服务"。有关您可以在那里找到的故障和错误扩展的更多信息。

    这是工作主机控制台应用程序。我不在那里使用IoC,只是Pure DI,但您可以轻松地使用您想要的任何IoC解析记录器:

    base.OnStarting()

    配置:

    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> 添加到参考文档