3

最近、JuvalLowyによるProgrammingWCF Services、ThirdEditionを読みました。以下に示す彼を活用して、 ParameterTracerInvoker : GenericInvokerNLOGを使用してログをトレースしています。呼び出されているものをフェッチするという、不可能かもしれないと思うことを除いて、それはうまく機能します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);
    }
}
4

2 に答える 2

2

私の完全な例

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;
        }

      }
于 2012-10-03T07:46:16.113 に答える