Câu trả lời trễ, nhưng bạn có thể tiêm phụ thuộc vào IErrorHandler
bằng cách tạo tùy chỉnh ServiceHost
, giả sử TestServiceHost
.
Trong bạn TestServiceHost
bạn cần làm:
- Thực hiện constructor với
IErrorHandler
tham số.
- Bên trong, tạo lớp lồng nhau riêng có tên
ErrorHandlerBehaviour
*, cần triển khai cả hai IServiceBehavior
và IErrorHandler
. Nó cũng phải có hàm tạo với tham số IErrorHandler
.
- Ghi đè phương thức
OnStarting()
, nơi bạn sẽ thêm ErrorHandlerBehaviour
vào hành vi dịch vụ. Tất cả hành vi phải được thêm trước base.OnStarting()
.
* ý tưởng đến từ ví dụ của Juval Lowy trong sách - "Lập trình WCF dịch vụ". Thông tin thêm về lỗi và tiện ích mở rộng lỗi mà bạn có thể tìm thấy ở đó.
Đây là ứng dụng bảng điều khiển máy chủ đang hoạt động. Tôi không sử dụng IoC đó, chỉ cần Pure DI, nhưng bạn có thể dễ dàng giải quyết logger với bất kỳ IoC bạn muốn:
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);
}
}
Và cấu hình:
<system.serviceModel>
<services>
<service name="ConsoleHost.TestService">
<endpoint address="net.tcp://localhost:8002/TestService"
binding="netTcpBinding"
contract="ConsoleHost.ITestService" />
</service>
</services>
</system.serviceModel>
Btw. Đảm bảo bạn đã thêm System.Runtime.Serialization
vào tài liệu tham khảo
Bạn cũng có sử dụng tiện ích mở rộng WCF Ninject không? –
@DanielMarbach: Tôi có phần mở rộng WCF, nhưng tôi không thấy bất cứ điều gì trong đó có thể giúp đỡ trong tình huống này. Có cái gì mà tôi có thể sử dụng? – zimdanen
@zimdanen bạn đã giải quyết vấn đề này chưa? Tốt nhất là tiêm ILogger mà không có IoC, nhưng với tinh khiết ... Pure DI. Chỉ cần tiêm một giao diện ILogger trong 'ServiceErrorHandler' của bạn – Marshall