【问题标题】:Using reflection on Request crashes w3wp.exe process在 Request 上使用反射会使 w3wp.exe 进程崩溃
【发布时间】:2016-05-02 16:47:12
【问题描述】:

这是我制作对象转储器的尝试:

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 崩溃,但我调用的是 Request.Inspect() 包裹在父 try-catch 块中;

【问题讨论】:

  • 请注意,StackOverflow(这是递归的常见结果)会杀死进程并且无法被捕获...

标签: c# reflection crash w3wp


【解决方案1】:

我不确定您使用的Request 的确切类型,所以我只是阅读了HttpRequest 类的文档。如果这不是您正在使用的,至少我可以让您了解正在发生的事情:

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

所以这个递归永远不会停止,你会填满你的调用堆栈,直到你得到一个StackOverflowException。这种异常无法在您的 catch 块中处理,因为堆栈(以及整个进程)已经损坏。


要解决这个问题,您需要某种递归检测来告诉您是否尝试检查已经检查过的对象。然后您可以在该点停止递归。
或者,您可以在一定深度停止递归。具体解决方案取决于您需要所有这些信息的目的。

【讨论】:

  • 这似乎是真的,虽然Request.RequestContext.HttpContext.Request != Request。我将深度限制为 10,并且该过程不再崩溃。
猜你喜欢
  • 2015-12-21
  • 1970-01-01
  • 2011-06-07
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
相关资源
最近更新 更多