对请求使用反射会导致w3wp.exe进程崩溃



下面是我制作对象转储程序的尝试:

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方法中的RequestRequest.Inspect())时,w3wp.exe进程崩溃,try-catch块无法完成它的工作。

实际发生了什么?微软说,只有未处理的异常才会导致w3wp.exe崩溃,但我调用的是封装在父try-catch块中的Request.Inspect()

我不确定您使用的Request的确切类型,所以我只阅读了HttpRequest类的文档。如果这不是你正在使用的,至少我可以告诉你发生了什么:

  1. HttpRequest类有一个类型为RequestContext的名为RequestContext的属性,因此您可以为该属性调用InspectObject
  2. RequestContext具有类型为HttpContextBase的属性HttpContext,因此您可以为该属性调用InspectObject
  3. HttpContextBase具有HttpRequest类型的名为Request的属性,该属性是当前请求,并且-是-您为该属性调用InspectObject,从1开始。再次因为是同一个实例

因此,这种递归永远不会停止,您将填充调用堆栈,直到获得StackOverflowException。这种异常不能在catch块中处理,因为堆栈(以及整个过程)已经损坏。


为了解决这个问题,你需要某种递归检测,如果你试图检查一个已经检查过的对象,它会告诉你。然后,您可以在该点停止递归
或者,您可以在某个深度停止递归。具体的解决方案取决于您需要这些信息的目的。

最新更新