来自 IOperationInvoker 的方法名称
本文关键字:方法 IOperationInvoker 来自 | 更新日期: 2023-09-27 18:33:23
我最近读了Juval Lowy的《Programming WCF Services, Third Edition》。我正在利用下面显示的他ParameterTracerInvoker : GenericInvoker
使用 NLOG 跟踪日志。它工作得很好,除了我认为可能不可能的一件事,那就是获取被调用MethodName
。正如您在PreInvoke
方法中看到的那样,我正在记录输入,而不是方法名称。有人知道如何检索方法名称吗?
public abstract class GenericInvoker : IOperationInvoker
{
internal readonly IOperationInvoker _oldInvoker;
public GenericInvoker(IOperationInvoker oldInvoker)
{
Debug.Assert(oldInvoker != null);
_oldInvoker = oldInvoker;
}
public virtual object[] AllocateInputs()
{
return _oldInvoker.AllocateInputs();
}
/// <summary>
/// Exceptions here will abort the call
/// </summary>
/// <returns></returns>
protected virtual void PreInvoke(object instance, object[] inputs)
{ }
/// <summary>
/// Always called, even if operation had an exception
/// </summary>
/// <returns></returns>
protected virtual void PostInvoke(object instance, object returnedValue, object[] outputs, Exception exception)
{ }
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
PreInvoke(instance, inputs);
object returnedValue = null;
object[] outputParams = new object[] { };
Exception exception = null;
try
{
returnedValue = _oldInvoker.Invoke(instance, inputs, out outputParams);
outputs = outputParams;
return returnedValue;
}
catch (Exception operationException)
{
exception = operationException;
throw;
}
finally
{
PostInvoke(instance, returnedValue, outputParams, exception);
}
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
PreInvoke(instance, inputs);
return _oldInvoker.InvokeBegin(instance, inputs, callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
object returnedValue = null;
object[] outputParams = { };
Exception exception = null;
try
{
returnedValue = _oldInvoker.InvokeEnd(instance, out outputs, result);
outputs = outputParams;
return returnedValue;
}
catch (Exception operationException)
{
exception = operationException;
throw;
}
finally
{
PostInvoke(instance, returnedValue, outputParams, exception);
}
}
public bool IsSynchronous
{
get
{
return _oldInvoker.IsSynchronous;
}
}
}
public class ParameterTracerInvoker : GenericInvoker
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
public ParameterTracerInvoker(IOperationInvoker oldInvoker)
: base(oldInvoker)
{
}
protected override void PreInvoke(object instance, object[] inputs)
{
//_logger.Trace(((SyncMethodInvoker)_oldInvoker).MethodName);
_logger.Trace("Input Parameters:");
foreach (object argument in inputs)
{
if (argument != null)
{
_logger.Trace(argument.ToString());
}
else
{
_logger.Trace("null");
}
}
}
protected override void PostInvoke(object instance, object returnedValue, object[] outputs, Exception exception)
{
foreach (object output in outputs)
{
_logger.Trace("Output Parameters:");
_logger.Trace(output.ToString());
}
returnedValue = "aaaaaaaaaaaa";
_logger.Trace("Returned: " + returnedValue ?? String.Empty);
}
}
IOperationInvoker
本身不会给你操作名称,但为了使用自定义调用程序,你通常会使用操作行为。该行为有权访问操作名称,并且可以将其传递给自定义调用程序:
public class ParameterTracerOperationBehavior : IOperationBehavior
{
// ...
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
var originalInvoker = dispatchOperation.Invoker;
var operationName = operationDescription.Name;
var newInvoker = new ParameterTracerInvoker(originalInvoker, operationName);
dispatchOperation.Invoker = newInvoker;
}
}
public class ParameterTracerInvoker
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly string operationName;
public ParameterTracerInvoker(IOperationInvoker oldInvoker, string operationName)
: base(oldInvoker)
{
this.operationName = operationName;
}
// ...
}
我的完整示例
public class WcfTracingOperationBehavior : IOperationBehavior
{
#region Implementation of IOperationBehavior
public void Validate(OperationDescription operationDescription)
{
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Invoker = new WcfTracingOperationInvoker(dispatchOperation.Invoker, operationDescription);
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
#endregion
}
和
public class WcfTracingOperationInvoker : IOperationInvoker
{
private readonly IOperationInvoker _originalInvoker;
private string ServiceFullName { get; set; }
private string ServiceName { get; set; }
private string MethodName { get; set; }
public WcfTracingOperationInvoker(IOperationInvoker originalInvoker, OperationDescription operationDescription)
{
_originalInvoker = originalInvoker;
var declaringType = operationDescription.SyncMethod.DeclaringType;
if (declaringType != null)
{
ServiceFullName = declaringType.FullName;
ServiceName = declaringType.Name;
}
MethodName = operationDescription.SyncMethod.Name;
}
#region Implementation of IOperationInvoker
public object[] AllocateInputs()
{
SetMethodInfo();
return _originalInvoker.AllocateInputs();
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var result = _originalInvoker.Invoke(instance, inputs, out outputs);
return result;
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return _originalInvoker.InvokeBegin(instance, inputs, callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
return _originalInvoker.InvokeEnd(instance, out outputs, result);
}
public bool IsSynchronous
{
get { return _originalInvoker.IsSynchronous; }
}
#endregion
private void SetMethodInfo()
{
// The WcfContext is some my stuff.
var wcfTraceActivity = WcfContext<WcfTraceActivity>.Current;
wcfTraceActivity.ServiceName = ServiceName;
wcfTraceActivity.ServiceFullName = ServiceFullName;
wcfTraceActivity.MethodName = MethodName;
}
}