There are some classes:
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";
}
}
and NoLog custom attribue:
public class NoLogAttribute : Attribute
{
}
According to your question you use sth like this to pretty print:
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);
}
}
}
I changed the way how we access properties (by name) and added for this two methods:
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;
}
where GetPropertiesToLogWithCaching is wrapper of GetPropertiesToLog. ChacheLayer object you can find here http://www.deanhume.com/home/blogpost/object-caching----net-4/37
Now it is recursive and it has caching. As I wrote in first version of answer. The idea is to chache list of properties names and than GetProperty by name without testing attributes as a key for cache we can use FullName of obj Type. Now you need to check how it works.