WCF 错误处理和访问类对象

Whi*_*uit 3 .net error-handling wcf

我已经使用 IErrorHandler 实现了一些基本的 WCF 错误处理,我可以在其中获取堆栈跟踪并记录它,但是我还想从导致异常的类中记录一些其他信息。

例如,假设我的服务中有以下课程:

Class Foo
    Public User As String
    Public PhoneNumber As String

    Public Function Bar() As Boolean
        Dim c As Collection 'intentionally not set to an object to cause an error below
        c.Add(PhoneNumber)
        Return True
    End Function
End Class
Run Code Online (Sandbox Code Playgroud)

我发现了以下错误:

  Public Function HandleError(ByVal [error] As System.Exception) As Boolean Implements ystem.ServiceModel.Dispatcher.IErrorHandler.HandleError
        'Log ex.tostring to event log
         'How can I access User and PhoneNumber?
        Return False
    End Function
Run Code Online (Sandbox Code Playgroud)

我现在有了错误的堆栈跟踪。但是我如何才能访问 User 和 PhoneNumber?虽然堆栈跟踪很有帮助,但在错误报告系统中引用导致错误的基础数据是最重要的。

Cod*_*ike 5

我做了类似的事情,但我没有在我的IErrorHandler扩展点中记录方法调用参数。相反,我最终在IOperationInvoker那里实现了自定义和处理参数日志记录。这是一个可能有用的代码片段:

public class MyOperationBehavior : IOperationBehavior
{
    public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    {
        // intentionally empty.
    }

    public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    {
        // intentionally empty.
    }

    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
    {
        // create a name for this operation for logging purposes.
        string operationName;
        if (operationDescription.SyncMethod != null)
            operationName = operationDescription.SyncMethod.DeclaringType.FullName + "." + operationDescription.Name;
        else if (operationDescription.BeginMethod != null)
            operationName = operationDescription.BeginMethod.DeclaringType.FullName + "." + operationDescription.Name;
        else operationName = operationDescription.Name;

        dispatchOperation.Invoker = new MyOperationInvoker(operationName, dispatchOperation.Invoker);
    }

    public void Validate(OperationDescription operationDescription)
    {
        // intentionally empty.
    }
}
Run Code Online (Sandbox Code Playgroud)

.

public class MyOperationInvoker : IOperationInvoker
{
    private readonly IOperationInvoker defaultInvoker;
    private readonly string operationName;

    public MyOperationInvoker(string operationName, IOperationInvoker defaultInvoker)
    {
        if(defaultInvoker == null)
            throw new ArgumentException("DefaultInvoker can not be null.");

        this.defaultInvoker = defaultInvoker;
        this.operationName = operationName;
    }

    public object[] AllocateInputs()
    {
        return defaultInvoker.AllocateInputs();
    }

    public object Invoke(object instance, object[] inputs, out object[] outputs)
    {
        Exception error = null;

        DoMySuperAwesomePreProcessing(operationName, inputs);

        try
        {
            return defaultInvoker.Invoke(instance, inputs, out outputs);
        }
        catch (Exception ex)
        {
            error = ex;
            throw;
        }
        finally
        {
            DoMySuperAwesomePostProcessing(operationName, inputs, error);
        }
    }

    public bool IsSynchronous
    {
        get { return defaultInvoker.IsSynchronous; }
    }
Run Code Online (Sandbox Code Playgroud)

所以基本上它会通过 调用它通常会调用的任何东西defaultInvoker,但是在调用之前和之后,它有机会与实例、输入、输出和异常进行交互(如果有的话)。

在那个后期处理点,如果我发现了一个错误,我最终会记录它,包括方法名称、所有输入参数以及所有记录的异常方法,因此我们可以尝试用相同的方法重现问题输入。

还仍然有一个自定义的IErrorHandler用于记录未处理的异常实现,我只是不从那里记录的参数,而不是我从上面的代码登录的参数。

希望这可以帮助!