本文介绍了将依赖项注入IErrorHandler实现中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实施IErrorHandler以便将WCF服务的所有错误处理集中在一处.效果很好:

I am implementing IErrorHandler in order to centralize all of the error handling for my WCF service in one place. This works fairly well:

public class ServiceErrorHandler : IErrorHandler
{

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

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

}

现在,我们正在使用Ninject在服务的其余部分中注入依赖项,我想在这里做同样的事情.由于WCF是根据我的配置构造对象的,并且我认为我对此过程没有任何迷惑,因此我需要使用属性注入:

Now, we're using Ninject to inject dependencies in the rest of the service, and I'd like to do the same here. Since WCF is constructing the objects based on my configuration, and I don't think I have any hooks into this process, I need to use property injection:

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

但是,这似乎从未被注入.我尝试使用Ninject的MVC扩展来设置ServiceErrorHandler以允许像过滤器一样进行注入,但是似乎并没有解决问题.有没有办法做到这一点?

However, this never seems to get injected. I tried using Ninject's MVC extensions to set ServiceErrorHandler to allow injection like a filter, but that didn't seem to do the trick. Is there a way to make this happen?

推荐答案

最新的答案,但是您可以通过创建自定义的ServiceHost(例如TestServiceHost)将依赖项注入到IErrorHandler中.

Late answer, but you can inject dependencies into IErrorHandler by creating your custom ServiceHost, let's say TestServiceHost.

在您的TestServiceHost中,您需要执行以下操作:

In your TestServiceHost you need to do:

  1. 使用IErrorHandler参数实现构造函数.
  2. 在内部,创建一个名为ErrorHandlerBehaviour *的私有嵌套类,该类需要同时实现IServiceBehaviorIErrorHandler.它还必须具有带有IErrorHandler参数的构造函数.
  3. 覆盖OnStarting()方法,您可以在其中将ErrorHandlerBehaviour添加到服务行为中.必须在base.OnStarting()之前添加所有行为.
  1. Implement constructor with IErrorHandler parameter.
  2. Inside, create a private nested class named ErrorHandlerBehaviour*, which needs to implement both IServiceBehavior and IErrorHandler. It also must have constructor with IErrorHandler parameter.
  3. Override OnStarting() method, where you will add ErrorHandlerBehaviour to service behaviours. All behaviours must be added before base.OnStarting().

*这个想法来自Juval Lowy在编程WCF服务"一书中的示例.您可以在此处找到有关故障和错误扩展的更多信息.

*the idea came from Juval Lowy's example in book - "Programming WCF Services". More information about Faults and Error extensions you can find there.

这是正在运行的主机控制台应用程序.我不在这里使用IoC,只是 Pure DI ,但是您可以轻松地使用以下方法解决记录器您想要的任何IoC:

Here is the working host console application. I don't use IoC there, just Pure DI, but you can easily resolve logger with any IoC you want:

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添加到引用中

Btw. Make sure you added System.Runtime.Serialization to your references

这篇关于将依赖项注入IErrorHandler实现中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-09 22:38