我有这种情况:我有WCF服务.我正在通过MyErrorHandler
实现的接口处理所有异常IErrorHandler
.整个工作代码如下.
我想做什么,但不知道如何:我想将一个对象(例如ILogger)注入到MyErrorHandler
类中.它基本上意味着我必须在这里注入一个对象:[GlobalErrorHandlerBehaviour(typeof(MyErrorHandler))]
.你能帮我解决一下这个问题吗?
[ServiceContract] public interface ITestService { [OperationContract] int GetTest(); } [GlobalErrorHandlerBehaviour(typeof(MyErrorHandler))] public class TestService : ITestService { public TestService(ILogger logger) { // Here, I'm already injecting logger. // It's not imported for my question so I removed it for now } public int GetTest() { throw new Exception("Test"); } } // This is attribute added to TestService class // How can I inject (via constructor) ILogger, or any other class?? public class GlobalErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior { private readonly Type errorHandlerType; public GlobalErrorHandlerBehaviourAttribute(Type errorHandlerType) { this.errorHandlerType = errorHandlerType; } public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collectionendpoints, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { IErrorHandler handler = (IErrorHandler)Activator.CreateInstance(errorHandlerType); foreach(ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers) { ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher; if (channelDispatcher != null) { channelDispatcher.ErrorHandlers.Add(handler); } } } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } } public class MyErrorHandler : IErrorHandler { //--------------------------------------------------// // I MUST INJECT ILOGGER HERE (or any other object) // //--------------------------------------------------// public bool HandleError(Exception error) { 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); } }
顺便说一句.我想使用DI并注入一些东西,IErrorHandler
我不想使用private static readonly
logger方法.
这个问题与你的问题有关.基本上,你不需要GlobalErrorHandlerBehaviourAttribute
.您可以手动向服务添加行为.你要做的就是创造你的ServiceHost
.在这个答案中,我更明确地解释了如何做到这一点.
这是主机应用程序的工作代码,它注入ILogger
了IErrorHandler
:
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, Collectionendpoints, 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); } }
配置: