有一些类:
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 自定义属性:
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
现在它是递归的并且具有缓存。正如我在答案的第一个版本中所写。我们的想法是在不测试属性的情况下按名称查询属性名称列表,而不是按名称获取属性作为缓存的键,我们可以使用 obj 类型的 FullName。现在你需要检查它是如何工作的。