C#中的递归日志对象属性

时间:2013-03-05 19:25:12

标签: c# .net wcf recursion

我想记录每个WCF参数的文件。我使用参数检查器并创建递归代码来检查所有输入中每个类的每个属性(我的代码类似于:How to recursively print the values of an object's properties using reflection)所以我可以登录文件,如:

MethodName(string="aaa", ComplexClass=[prop="aaa", prop2="bbb"])

不幸的是,我必须更改我的代码,以便不记录使用名为NoLog的自定义属性标记的属性。我修改了我的代码以获取每个属性的属性,但因为每次我检查参数时我的代码都会慢下来。

所以我的问题是:我如何提供缓存?

1 个答案:

答案 0 :(得分:3)

有一些课程:

public class A
{
    public int Id { get; set; }
    public B BValue { get; set; }

    public A()
    {
        this.Id = 1000;
        this.BValue = new B();
    }
}

public class B
{
    public string Name { get; set; }
    public C CValue { get; set; }
    [NoLog]
    public string Secret { get; set; }

    public B()
    {
        this.Name = "Empty Name";
        this.CValue = new C();
    }
}

public class C
{
    public string Description { get; set; }

    public C()
    {
        this.Description = "Empty Description";           
    }
}

和NoLog custom attribue:

public class NoLogAttribute : Attribute
{

}

根据你的问题,你可以用这样的方式打印出来:

public static void PrintProperties(object obj, int indent = 4, char intendCharacter = ' ')
    {
        if (obj == null) return;
        string indentString = new string(intendCharacter, indent);
        Type objType = obj.GetType();
        foreach (var pName in GetPropertiesToLogWithCaching(obj))
        {
            var property = objType.GetProperty(pName);
            object propValue = property.GetValue(obj, null);
            if (property.PropertyType.Assembly == objType.Assembly)
            {
                Console.WriteLine("{0}{1}:", indentString, property.Name);
                PrintProperties(propValue, indent + 2);
            }
            else
            {
                Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
            }
        }            
    }

我改变了访问属性(按名称)的方式,并添加了这两种方法:

public static List<string> GetPropertiesToLogWithCaching(object obj)
    {
        List<string> propertiesToLog = new List<string>();
        if (obj != null)
        {
            string key = obj.GetType().FullName;
            propertiesToLog = CacheLayer.Get<List<string>>(key);
            if (propertiesToLog == null)
            {
                propertiesToLog = GetPropertiesToLog(obj);
                CacheLayer.Add<List<string>>(propertiesToLog, key);
            }
        }
        return propertiesToLog;
    }

    public static List<string> GetPropertiesToLog(object obj)
    {
        List<string> propertiesToLog = new List<string>();
        if (obj != null)
        {
            foreach (var p in obj.GetType().GetProperties().Where(prop => !Attribute.IsDefined(prop, typeof(NoLogAttribute))))
            {                   
                propertiesToLog.Add(p.Name);
            }
        }
        return propertiesToLog;
    }

其中GetPropertiesToLogWithCaching是GetPropertiesToLog的包装。您可以在此处找到ChacheLayer对象http://www.deanhume.com/home/blogpost/object-caching----net-4/37

现在它是递归的,它有缓存。正如我在第一版的答案中写的那样。我们的想法是按名称查找属性名称列表而不是GetProperty,而不测试属性作为缓存的键,我们可以使用obj Type的FullName。现在你需要检查它是如何工作的。