我正在实现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到你的引用