Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method name from IOperationInvoker

Tags:

c#

wcf

I recently read Programming WCF Services, Third Edition by Juval Lowy. I am leveraging his ParameterTracerInvoker : GenericInvoker shown below to trace log using NLOG. It works great except for one thing that I think might not be possible, which is fetching the MethodName being called. As you can see in the PreInvoke method, I am logging the inputs, but not the method name. Anyone know how the method name could be retrieved?

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);
    }
}
like image 613
DapperDanh Avatar asked Dec 13 '25 15:12

DapperDanh


1 Answers

The IOperationInvoker itself won't give you the operation name, but in order to use a custom invoker you'd normally use an operation behavior. The behavior has access to the operation name, and that can be passed to your custom invoker:

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

    // ...
}
like image 122
carlosfigueira Avatar answered Dec 15 '25 06:12

carlosfigueira



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!