我做了类似的事情,但我没有在IErrorHandler 扩展点中记录方法调用参数。相反,我最终实现了一个自定义 IOperationInvoker 并在那里处理参数日志记录。这是一个可能有用的代码 sn-p:
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.
}
}
.
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; }
}
所以基本上它通过defaultInvoker 调用它通常会调用的任何东西,但是在调用之前和之后,它有机会与实例、输入、输出和异常进行交互(如果抛出一个)。
在那个后处理点,如果我发现一个错误,我最终会记录它,方法名称、所有输入参数和异常方法都记录下来,所以我们可以尝试重现问题输入相同。
我确实还有一个自定义的IErrorHandler 实现来记录未处理的异常,我只是不从那里记录参数,而是从上面的代码中记录参数。
希望这会有所帮助!