我正在实现IErrorHandler,以便将WCF服务的所有错误处理集中在一个地方。这样做的效果相当好:
public class ServiceErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
// ..Log..
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
// ..Provide fault..
}
}现在,我们使用like在服务的其余部分中注入依赖项,我也想在这里这样做。由于WCF是基于我的配置构建对象的,而且我认为我在这个过程中没有任何挂钩,所以我需要使用属性注入:
[Inject]
public ILoggingService Logger { get; set; }然而,这似乎从来没有被注射。我试着使用Ninject的MVC扩展来设置ServiceErrorHandler,使其像过滤器一样允许注入,但这似乎没有起作用。有什么办法让这事发生吗?
发布于 2015-12-21 12:34:05
迟答,但您可以通过创建自定义的IErrorHandler (例如TestServiceHost )将依赖项注入到ServiceHost中。
在您的TestServiceHost中,您需要这样做:
IErrorHandler参数实现构造函数。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, 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添加到引用中
https://stackoverflow.com/questions/18113345
复制相似问题