Click here to Skip to main content
Click here to Skip to main content

Log All Parameters that were Passed to Some Method in C#

, 13 Jul 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Log All Parameters that were passed to some method in C#

Introduction

Exception is a common issue in projects. To track this exception, we use error loggers which only log the exception detail and some other information if you want to. But hardly do we get any idea for which input set(parameters and its values) a particular method is throwing the error.

ParamLogUtility

This is the utility which we can use to trace Parameters values during exception.

internal class ParamLogUtility
{
    private readonly String _methodName;
    private String _paramaterLog;

    private readonly JavaScriptSerializer _serializer;
    private readonly Dictionary<String, Type> _methodParamaters;
    private readonly List<Tuple<String, Type, object>>_providedParametars;

    public ParamLogUtility(params Expression<Func<object>>[] providedParameters)
    {
        try
        {
            _serializer = new JavaScriptSerializer();
            var currentMethod = new StackTrace().GetFrame(1).GetMethod();

            /*Set class and current method info*/
            _methodName = String.Format("Class = {0}, Method = {1}", 
            currentMethod.DeclaringType.FullName, currentMethod.Name);
            
            /*Get current methods parameters*/
            _methodParamaters = new Dictionary<string, Type>();
            (from aParamater in currentMethod.GetParameters()
                select new { Name = aParamater.Name, DataType = aParamater.ParameterType })
                .ToList()
                .ForEach(obj => _methodParamaters.Add(obj.Name, obj.DataType));

            /*Get provided methods parameters*/
            _providedParametars = new List<Tuple<string, Type, object>>();
            foreach (var aExpression in providedParameters)
            {
                Expression bodyType = aExpression.Body;
                if (bodyType is MemberExpression)
                {                    AddProvidedParamaterDetail((MemberExpression)aExpression.Body);
                }
                else if (bodyType is UnaryExpression)
                {
                    UnaryExpression unaryExpression = (UnaryExpression)aExpression.Body;
                    AddProvidedParamaterDetail((MemberExpression)unaryExpression.Operand);
                }
                else
                {
                    throw new Exception("Expression type unknown.");
                }
            }

            /*Process log for all method parameters*/
            ProcessLog();
        }
        catch (Exception exception)
        {
            throw new Exception("Error in paramater log processing.", exception);
        }
    }
    private void ProcessLog()
    {
        try
        {
            foreach (var aMethodParamater in _methodParamaters)
            {
                var aParameter =
                    _providedParametars.Where(
                        obj => obj.Item1.Equals(aMethodParamater.Key) && 
                obj.Item2 == aMethodParamater.Value).Single();
                _paramaterLog += String.Format(@" ""{0}"":{1},", 
            aParameter.Item1, _serializer.Serialize(aParameter.Item3));
            }
            _paramaterLog = (_paramaterLog != null) ? _paramaterLog.Trim(' ', ',') : string.Empty;
        }
        catch (Exception exception)
        {
            throw new Exception("MathodParamater is not found in providedParameters.");
        }
    }

    private void AddProvidedParamaterDetail(MemberExpression memberExpression)
    {
        ConstantExpression constantExpression = (ConstantExpression) memberExpression.Expression;
        var name = memberExpression.Member.Name;
        var value = ((FieldInfo) memberExpression.Member).GetValue(constantExpression.Value);
        var type = value.GetType();
        _providedParametars.Add(new Tuple<string, Type, object>(name, type, value));
    }

    public String GetLog()
    {
        return String.Format("{0}({1})", _methodName, _paramaterLog);
    }
}

Using the Code

To use the code, we have to add System.Web.Extensions.dll reference at our project, which is located somewhere around this location, if we don't find it from reference explorer:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Web.Extensions.dll

If the method contains any parameter.

private void Add(string id, int age, string name, PersonEntity aPersonEntity)
{
    try
    {
        throw new NotImplementedException();
    }
    catch (Exception exception)
    {
        /*gives the log*/
        var paramLog = new ParamLogUtility(() => aPersonEntity, 
        () => age, () => id, () => name).GetLog();
    }
}

It is not important that all methods should have parameters. If there is no parameter, we can use it like:

var paramLog = new ParamLogUtility().GetLog();

Log String Sample

Class = MethodParamatersLog.Program, Method = Add("id":"1", 
"age":24, "name":"Dipon", 
"aPersonEntity":{"CreatedDateTime":"\/Date(1405115574273)\/",
"Id":"1","Name":"Dipon","Age":24})

Limitation

This logger does have some limitations like:

  1. Only parameters pacified at method signature could participate in log process. If we add some extra variables to the process, it would throw an error as here aPersonEntity is not part of the method signature.
    private static void Add(string id, int age, string name)
    {
        PersonEntity aPersonEntity = new PersonEntity();
        try
        {
            throw new NotImplementedException();
        }
        catch (Exception exception)
        {
            /*aPersonEntity would not take part in log process, 
              as it is not used in methods signature, and with throw error
            */
            var paramLog = new ParamLogUtility(() => aPersonEntity, () => age, 
            () => id, () => name).GetLog();
            var error = exception;
        }
    } 
  2. All the parameters of the method sunbather variables must take part in log process. If not, it would throw an error.

    This is important because sometimes we may forget to add method parameters to the log string. This error will remind us to use thus unused parameters.

    private static void Add(string id, int age, string name)
    {
        PersonEntity aPersonEntity = new PersonEntity();
        try
        {
            throw new NotImplementedException();
        }
        catch (Exception exception)
        {
            /*did n't pointed all the parameters of the method(id, age)*/
            var paramLog = new ParamLogUtility(() => name).GetLog();
            var error = exception;
        }
    }
  3. There can be some other errors too, which I haven’t faced yet, so if you find any, please let me know.

You can find the sample project of VS 2013 solution in the attachment.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

DiponRoy

Bangladesh Bangladesh
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 PinmemberCarlos190714-Jul-14 1:34 
GeneralRe: My vote of 5 Pinmemberdiponsust14-Jul-14 2:02 
GeneralRe: My vote of 5 PinmemberCarlos190714-Jul-14 2:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150327.1 | Last Updated 13 Jul 2014
Article Copyright 2014 by DiponRoy
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid