【问题标题】:Why 'dynamic' ExpandoObject throws RuntimeBinderException even if it contains the definition for a property?为什么“动态”ExpandoObject 会抛出 RuntimeBinderException,即使它包含属性的定义?
【发布时间】:2015-01-30 15:18:40
【问题描述】:

使用以下示例代码:(VS 2013,更新 3)

dynamic demo = new ExpandoObject();
demo.Test = 10;
var j = demo.Test; // throws exception

在调试此代码时 'Break when an exception is: 'Thrown'' 在 VS 中检查然后尝试访问 existing 属性 'Test' 会抛出一个 @ 987654326@:

System.Dynamic.ExpandoObject' 不包含“测试”的定义

注意:跳到下一行,变量 j 正确设置为 10。



Q1:为什么会抛出异常,当Test属性肯定存在并且持有值10时,事实变量j已经成功设置了这个值?当我尝试使用像 Test2 这样的真正不存在的属性名称时,会发生完全相同的异常,不同之处在于代码确实会以未处理的异常跳出块......

抛出一个完全错误和误导性的异常,然后在内部处理它只是没有意义,除了它呈现 VS 'Break when an exception is: 'Thrown' 选项功能实际上无法用于使用动态对象的代码。

Q2:是的,我知道这个问题可以通过取消选中“异常时中断:“抛出”选项来隐藏。 但是,如果开发人员使用动态对象并尝试在她/他的代码中查找与动态对象完全无关的异常,则这不是一个选项,此问题使“异常时中断:”抛出“选项不可用,因为那么调试器将停止数以千计的正确属性访问语句。有什么解决办法吗?

我错过了什么?

提前致谢。


* 编辑 * 此编辑在正确答案之后。

Damir 在他的回答中问道“为什么我在 VS 选项中禁用了 Enable Just My Code?”好吧,这就是答案......我被这个问题困扰了几天,并且经历了尽管我明确检查了 Just My Code 选项,但它在 VS 关闭/启动会话之间不会持续存在。终于知道为什么了……

【问题讨论】:

  • 不应该发生。查看 ExpandoObject 的来源:referencesource.microsoft.com/#System.Core/Microsoft/Scripting/….
  • Ricardo,你想要一个视频作为证明,还是相信我不是 PhotoShop 编辑的图片 :-)
  • 在 .NET Framework 中有几十个异常被抛出、捕获和正确处理。为什么不简单地为该特定异常禁用“抛出时中断”选项,并为所有其他异常启用它?
  • 转载。但我需要取消选中Enable Just My Code(在选项、调试、常规中)才能看到异常,参见。 Damir Arh 的“答案”。
  • @leppie 堆栈跟踪只有一个“帧”,看起来像这样:" at Microsoft.CSharp.RuntimeBinder.RuntimeBinderController.SubmitError(CError pError)"

标签: c# .net exception


【解决方案1】:

为什么您在 VS 选项中禁用了 Enable Just My Code

现在您将在“异常”对话框中获得一个附加选项,以仅在您未在代码中处理的异常上中断:

如果你像这样配置 VS,当这些内部处理的异常被抛出时,调试器将不再中断。

【讨论】:

  • 另外,第一次弹出RuntimeBinderException发生时,他可以去掉Break when this exception type is throwed。然后他将不再看到RuntimeBinderException 实例。如果他愿意,他仍然可以在自己的代码和 BCL 代码中看到其他异常(甚至是已处理的异常)。
  • 谢谢达米尔。这绝对是一种解决方法,我错过了。不是一个实际的问题(我的意思是有人可以说:谁在乎?)但仍然:为什么在地球上有人抛出并抓住自己/他自己一个异常“System.Dynamic.ExpandoObject'不包含'Test'的定义”当它肯定包含...?
  • @g.pickardou 可能是因为dynamic 可以通过多种方式找到成员。也许(只是猜测)它首先尝试使用失败并抛出的反射来查找 Test 属性,捕获该异常,然后才继续搜索以查看该属性是否以某种不同的方式可用。
  • @hvd 在正常使用场景下抛出数千个异常是一个坏主意。没有办法解释和推理。在您解释的这种特殊情况下:通过反射,我们始终可以获取存在的属性,或者在尝试访问不存在的属性之前获取特定属性是否存在。 :
  • @g.pickardou 我不知道缓存的具体内容,但我知道缓存正在进行,所以不会有成千上万的异常。
【解决方案2】:

我通过使用“Jeppe Stig Nielsen”的评论解决了这个问题。只需在抛出该异常类型时取消勾选 Break,调试器将不再阻止代码运行。

【讨论】:

    【解决方案3】:

    我最近遇到了这个问题,这是因为我试图将一个对象添加到一个列表中,该列表是 ExpandoObject 的一个属性,而不是先初始化列表。

    var someObjectInstance = new someObject();
    var sampleExpando = new ExpandoObject();
    sampleExpando.someObjects.Add(someObjectInstance);
    

    上面给了我运行时绑定错误,通过以下方法解决:

    var someObjectInstance = new someObject();
    var sampleExpando = new ExpandoObject();
    sampleExpando.someObjects = new List<someObject>();
    sampleExpando.someObjects.Add(someObjectInstance);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-20
      相关资源
      最近更新 更多