65.9K
CodeProject 正在变化。 阅读更多。
Home

C#: 记录传递给方法的所有参数

2014年7月13日

CPOL

1分钟阅读

viewsIcon

59891

downloadIcon

501

在 C# 中记录传递给某个方法的所有参数

引言

异常在任何项目中都很常见。为了跟踪异常,我们使用错误记录器,这些记录器可能只会记录异常细节和一些额外的信息。但我们很难知道对于哪一组输入(参数和值)方法抛出了错误。

参数记录实用工具

这里是实用工具类,我们可以使用它来跟踪异常期间的 参数 值。

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);
    }
}
  • 在构造函数内部,ParamLogUtility(params Expression<Func<object>>[] providedParameters) 我们将传递所有期望的方法参数。
  • GetLog() 将返回错误日志字符串

使用日志实用工具

要使用这段代码,我们可能需要在我们的项目中添加 System.Web.Extensions.dll 引用,该引用位于以下位置附近

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

如果方法包含任何参数,我们将像这样使用该实用工具类

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

并非所有方法都应该有参数。如果没有参数,我们可以像这样使用它

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

日志字符串示例

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

限制

这个记录器有一些限制,例如

  1. 只有在方法签名中指定的参数才能参与日志过程。如果在过程中添加一些额外的变量,它会抛出一个错误,例如这里 aPersonEntity 不是方法签名的一部分。
    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. 方法的全部参数都应该参与日志过程。否则,它会抛出一个错误。这一点很重要,因为我们有时可能会忘记将方法参数添加到日志字符串中。这个错误会提醒我们使用这些未使用的参数。
    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. 也可能存在其他我尚未遇到的错误。所以如果您发现任何错误,请告诉我。
  4. 我们应该将这个实用工具应用到每个方法吗?显然不是!

您可以在附件中找到 VS 2013 解决方案的示例项目。

历史

  • 2014 年 7 月 13 日:初始版本
© . All rights reserved.