使用 IErrorHandler 接口,我们可以更深入地参与到 WCF 的异常处理过程当中。我们甚至可以改变异常消息细节,而不仅仅是做些错误记录。
public interface IErrorHandler
{
void ProvideFault(Exception error, MessageVersion version, ref Message fault);
bool HandleError(Exception error);
}
ProvideFault 方法在服务方法发生异常,WCF 返回异常消息,终止会话之前被调用。该方法通常被用来修改返回的异常消息,诸如进行重新包装等等。由于调用 ProvideFault 时,客户端处于阻塞状态,因此不要在其内部做长时间的处理,以免客户端超时。而 HandleError 在异常返回给客户端之后被触发,因此它不会阻塞通讯。多数时候只是用来完成异常记录,进行错误提示等操作。
要使用 IErrorHandler, 除了创建一个具体类型外,还要使用另外一个接口 —— IServiceBehavior。通过 IServiceBehavior 我们可以将自己的 ErrorHandler 安装到 Channel Dispatcher 异常处理集合当中。IServiceBehavior 接口有三个方法,我们只用到 ApplyDispatchBehavior(),而另外两个可以不用管它。
[ServiceContract]
public interface IService
{
[OperationContract]
void Test();
}
public class ErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
Console.WriteLine("HandleError:{0}", error.Message);
return false;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (error is IOException)
{
FaultException<int> e = new FaultException<int>(123, "IO Exception...");
MessageFault m = e.CreateMessageFault();
fault = Message.CreateMessage(version, m, e.Action);
}
}
}
public class Service : IService, IDisposable, IServiceBehavior
{
public void Test()
{
throw new IOException();
}
public void Dispose()
{
Console.WriteLine("Dispose...");
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
IErrorHandler handler = new ErrorHandler();
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add(handler);
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ...)
{
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
|