下面是我制作对象转储程序的尝试:
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace Inspector
{
public static class Inspector
{
public static string Inspect(this object o)
{
StringBuilder sb = new StringBuilder();
InspectObject(o, sb);
return sb.ToString();
}
private static void InspectObject(object o, StringBuilder sb)
{
Type objType = o.GetType();
if (objType == typeof(string))
sb.Append(o.ToString());
else
{
try
{
IList<PropertyInfo> props = new List<PropertyInfo>(objType.GetProperties());
foreach (PropertyInfo prop in props)
{
object propValue = null;
ParameterInfo[] ip = prop.GetIndexParameters();
if (ip.Length == 0)
{
propValue = prop.GetValue(o, null);
InspectObject(propValue, sb);
}
else
{
}
}
}
catch (Exception ex)
{
sb.Append(string.Format("Exception: {0}", ex.Message));
}
}
}
}
}
当我使用它来检查HomeController的Index方法中的Request
(Request.Inspect()
)时,w3wp.exe进程崩溃,try-catch块无法完成它的工作。
实际发生了什么?微软说,只有未处理的异常才会导致w3wp.exe崩溃,但我调用的是封装在父try-catch块中的Request.Inspect()
;
我不确定您使用的Request
的确切类型,所以我只阅读了HttpRequest类的文档。如果这不是你正在使用的,至少我可以告诉你发生了什么:
HttpRequest
类有一个类型为RequestContext
的名为RequestContext
的属性,因此您可以为该属性调用InspectObject
- 该
RequestContext
具有类型为HttpContextBase
的属性HttpContext
,因此您可以为该属性调用InspectObject
- 此
HttpContextBase
具有HttpRequest
类型的名为Request
的属性,该属性是当前请求,并且-是-您为该属性调用InspectObject
,从1开始。再次因为是同一个实例
因此,这种递归永远不会停止,您将填充调用堆栈,直到获得StackOverflowException
。这种异常不能在catch
块中处理,因为堆栈(以及整个过程)已经损坏。
为了解决这个问题,你需要某种递归检测,如果你试图检查一个已经检查过的对象,它会告诉你。然后,您可以在该点停止递归
或者,您可以在某个深度停止递归。具体的解决方案取决于您需要这些信息的目的。