【问题标题】:Why does the assignment from a dynamic object throw a RuntimeBinderException?为什么来自动态对象的赋值会引发 RuntimeBinderException?
【发布时间】:2015-09-22 04:58:31
【问题描述】:

为什么这段代码会抛出 RuntimeBinderException,我该如何解决这个问题?为什么我不能在 catch 块中捕捉到这个异常?

如果我使用System.Web.Helpers.Json.Decode(response) 解析json字符串也会出现同样的错误。

using Microsoft.CSharp.RuntimeBinder;
using Newtonsoft.Json;
using System;
using System.Windows;

namespace DynamicDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        try
        {
            String response = "{ \"data\":{ \"accountId\":\"YOUR_ACCOUNT_ID\"},\"message\":null}";
            dynamic obj = JsonConvert.DeserializeObject(response);
            String account = obj.data.accountId;
            Console.WriteLine(account);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

    }
}

}

然后输出...

'DynamicDemo.vshost.exe' (CLR v4.0.30319: DynamicDemo.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework.Aero2\v4.0_4.0.0.0__31bf3856ad364e35\PresentationFramework.Aero2.dll'. Symbols loaded.
'DynamicDemo.vshost.exe' (CLR v4.0.30319: DynamicDemo.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Numerics\v4.0_4.0.0.0__b77a5c561934e089\System.Numerics.dll'. Symbols loaded.
'DynamicDemo.vshost.exe' (CLR v4.0.30319: DynamicDemo.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Dynamic\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Dynamic.dll'. Symbols loaded.
Exception thrown: 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' in Microsoft.CSharp.dll
'DynamicDemo.vshost.exe' (CLR v4.0.30319: DynamicDemo.vshost.exe): Loaded 'Anonymously Hosted DynamicMethods Assembly'. 
Exception thrown: 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' in Microsoft.CSharp.dll   
Exception thrown: 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' in Microsoft.CSharp.dll
YOUR_ACCOUNT_ID
'DynamicDemo.vshost.exe' (CLR v4.0.30319: DynamicDemo.vshost.exe): Loaded 'C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 14.0\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CLIENTDIAGNOSTICS\XAMLDIAGNOSTICS\x86\WpfXamlDiagnosticsTap.dll'. Symbols loaded.
'DynamicDemo.vshost.exe' (CLR v4.0.30319: DynamicDemo.vshost.exe): Loaded 'C:\Windows\assembly\GAC\Microsoft.VisualStudio.OLE.Interop\7.1.40304.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.OLE.Interop.dll'. Module was built without symbols.
'DynamicDemo.vshost.exe' (CLR v4.0.30319: DynamicDemo.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\UIAutomationTypes\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationTypes.dll'. Symbols loaded.

更新 1: 更改了异常处理程序以捕获所有异常,但没有任何区别

【问题讨论】:

  • 不过,您的代码可以工作。它在输出中打印YOUR_ACCOUNT_ID。这些异常可能在 JsonConvert 中被捕获和处理。
  • 我们在控制台中看到“YOUR_ACCOUNT_ID”输出的事实让我认为您在此处显示的代码中可能不会发生异常。您是否尝试过在调试器中单步执行?
  • 看来您需要告诉方法要将对象反序列化到哪个类。我认为您可以通过指定对象类型或作为 DeserializeObject 方法的类型参数来做到这一点。另外,您是否检查过 RuntimeBinderException 在冒泡时没有更改为另一种异常类型?
  • 在你的捕获中,写一个 e.Message 以便我们可以看到一些细节。
  • 试过了,但是即使使用通用异常处理程序也不会执行 catch 块

标签: c#


【解决方案1】:

这完全正常。通过强制调试器在第一次机会异常上停止可以看到一些东西。您可能已经不小心打开了一个选项。

  • “Newtonsoft.Json.Linq.JObject”不包含“数据”的定义
  • “Newtonsoft.Json.Linq.JObject”不包含“accountId”的定义
  • 无法将类型“Newtonsoft.Json.Linq.JValue”隐式转换为“字符串”。存在显式转换(您是否缺少演员表?)

所有这些都是准确的。您正在看到 DLR 探寻可能 种方法来找回该属性。没有一种明显的方法起作用,在第二次尝试之后,它尝试了 JObject 实现的IDictionary&lt;string, JToken&gt; 接口。几乎在那里,除了 JToken 值需要强制转换。第 4 次尝试很好。

除了这些例外的成本之外,您没有真正的问题。这是严格限制的,您可以再次调用 JsonConvert.DeserializeObject() 并注意您现在 不要 得到异常。 DLR 已记住最优策略。

一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 2014-03-09
    • 1970-01-01
    • 2019-01-27
    相关资源
    最近更新 更多