加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

wcf – 将依赖项注入到IErrorHandler实现中

发布时间:2020-12-13 20:24:52 所属栏目:百科 来源:网络整理
导读:我正在实现IErrorHandler,以便将WCF服务的所有错误处理集中在一个位置.这样做相当好: public class ServiceErrorHandler : IErrorHandler{ public bool HandleError(Exception error) { // ..Log.. } public void ProvideFault(Exception error,MessageVers
我正在实现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以允许像过滤器那样进行注入,但是似乎并没有这样做.有没有办法让这种情况发生?

迟到的答案,但您可以通过创建您的自定义ServiceHost注入依赖关系,假设TestServiceHost.

在您的TestServiceHost中,您需要做:

>使用IErrorHandler参数实现构造函数.
> Inside,创建一个名为ErrorHandlerBehaviour *的私有嵌套类,它需要实现IServiceBehavior和IErrorHandler.它也必须具有IErrorHandler参数的构造函数.
>覆盖OnStarting()方法,您将在其中添加ErrorHandlerBehaviour到服务行为.所有行为必须在base.OnStarting()之前添加.

*这个想法来自于Juval Lowy的例子 – “编程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,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,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到你的引用

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读