Wcf 将依赖项注入IErrorHandler实现
我正在实现Wcf 将依赖项注入IErrorHandler实现,wcf,ninject,ierrorhandler,Wcf,Ninject,Ierrorhandler,我正在实现IErrorHandler,以便将我的WCF服务的所有错误处理集中在一个地方。这样做效果相当好: public class ServiceErrorHandler : IErrorHandler { public bool HandleError(Exception error) { // ..Log.. } public void ProvideFault(Exception error, MessageVersion versio
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
)将依赖项注入IErrorHandler
)
在TestServiceHost
中,您需要执行以下操作:
IErrorHandler
参数实现构造函数errorHandlerBehavior
*的私有嵌套类,该类需要实现IServiceBehavior
和IErrorHandler
。它还必须具有带有IErrorHandler
参数的构造函数OnStarting()
方法,您将在其中向服务行为添加ErrorHandlerBehavior
。必须在base.onStart()之前添加所有行为
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.Collections.ObjectModel;
使用System.ServiceModel;
使用System.ServiceModel.Channel;
使用System.ServiceModel.Description;
使用System.ServiceModel.Dispatcher;
名称空间控制台主机
{
班级计划
{
静态void Main(字符串[]参数)
{
变量记录器=新的DummyLogger();
var errorHandler=新的TestErrorHandler(记录器);
ServiceHost主机=新的TestServiceHost(errorHandler,typeof(TestService)),新的Uri(“net。tcp://localhost:8002"));
host.Open();
控制台写入线(“按回车键退出”);
Console.ReadKey();
}
}
[服务合同]
公共接口ITestService
{
[经营合同]
字符串测试(int输入);
}
公共类TestService:ITestService
{
公共字符串测试(int输入)
{
抛出新异常(“测试异常!”);
}
}
公共类TestErrorHandler:IErrorHandler
{
专用ILogger记录器{get;}
公共测试仪指针(ILogger记录器)
{
记录器=记录器;
}
公共布尔句柄错误(异常错误)
{
Logger.Log(错误消息);
返回true;
}
public void providefaulture(异常错误,消息版本,ref消息错误)
{
FaultException fe=新的FaultException();
MessageFault message=fe.CreateMessageFault();
fault=Message.CreateMessage(版本,消息,空);
}
}
公共类TestServiceHost:ServiceHost
{
私有只读IErrorHandler errorHandler;
公共TestServiceHost(IErrorHandler errorHandler,类型serviceType,参数Uri[]基地址)
:base(服务类型、基本地址)
{
this.errorHandler=errorHandler;
}
受保护的覆盖无效打开()
{
Description.Behaviors.Add(新的ErrorHandlerBehavior(errorHandler));
base.OnOpening();
}
类ErrorHandlerBehavior:IServiceBehavior,IErrorHandler
{
私有只读IErrorHandler errorHandler;
公共errorHandler行为(IErrorHandler errorHandler)
{
this.errorHandler=errorHandler;
}
bool IErrorHandler.HandleError(异常错误)
{
返回errorHandler.HandleError(错误);
}
void IErrorHandler.providDefault(异常错误、MessageVersion版本、ref消息错误)
{
errorHandler.ProviderDefault(错误、版本、参考故障);
}
无效IServiceBehavior.ApplyDispatchBehavior(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
foreach(serviceHostBase.ChannelDispatchers中的ChannelDispatcher ChannelDispatcher)
{
channelDispatcher.ErrorHandlers.Add(此);
}
}
void IServiceBehavior.AddBindingParameters(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase,集合终结点,BindingParameterCollection bindingParameters)
{
}
无效IServiceBehavior.Validate(ServiceDescription ServiceDescription,ServiceHostBase ServiceHostBase)
{
}
}
}
//虚拟记录器
公共接口ILogger
{
无效日志(字符串输入);
}
公共类DummyLogger:ILogger
{
公共作废日志(字符串输入)=>Console.WriteLine(输入);
}
}
和配置:
<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
您也使用了Ninject WCF扩展吗?@DanielMarbach:我有WCF扩展,但我看不到其中有任何东西对这种情况有帮助。有什么我可以用的吗?@zimdanen你解决这个问题了吗?最好是在没有国际奥委会的情况下注入ILogger,但使用纯。。。纯DI。只需在您的ServiceErrorHandler
@Marshall中插入一个接口ILogger即可。马歇尔:我们是usi