我正在实现 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 在服务的其余部分注入(inject)依赖项,我也想在这里做同样的事情。由于 WCF 正在根据我的配置构造对象,并且我认为我在此过程中没有任何 Hook ,因此我需要使用属性注入(inject):
[Inject]
public ILoggingService Logger { get; set; }
然而,这似乎永远不会被注入(inject)。我尝试使用 Ninject 的 MVC 扩展来设置
ServiceErrorHandler
允许像过滤器一样注入(inject),但这似乎没有奏效。有没有办法做到这一点?
最佳答案
迟到的答案,但您可以将依赖项注入(inject) IErrorHandler
通过创建您的自定义 ServiceHost
,假设 TestServiceHost
.
在您的 TestServiceHost
你需要做:
IErrorHandler
实现构造函数范围。 ErrorHandlerBehaviour
的私有(private)嵌套类*,需要同时实现IServiceBehavior
和 IErrorHandler
.它还必须有带有 IErrorHandler
的构造函数范围。 OnStarting()
方法,您将在其中添加 ErrorHandlerBehaviour
服务行为。所有行为必须在base.OnStarting()
之前添加. *这个想法来自 Juval Lowy 在“Programming WCF Services”一书中的示例。您可以在此处找到有关故障和错误扩展的更多信息。
这是工作主机控制台应用程序。我不在那里使用 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
给你的引用
关于wcf - 将依赖项注入(inject) IErrorHandler 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18113345/