处理动态时,第一次有机会抛出 Microsoft.CSharp.RuntimeBinderExceptions

问题描述 投票:0回答:3

我在 C# 中有一个标准的“动态字典”类型类 -

class Bucket : DynamicObject
{
    readonly Dictionary<string, object> m_dict = new Dictionary<string, object>();

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        m_dict[binder.Name] = value;
        return true;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return m_dict.TryGetValue(binder.Name, out result);
    }
}

现在我这样称呼它:

static void Main(string[] args)
{
    dynamic d = new Bucket();
    d.Name = "Orion"; // 2 RuntimeBinderExceptions
    Console.WriteLine(d.Name); // 2 RuntimeBinderExceptions
}

应用程序执行您期望的操作,但调试输出如下所示:

Microsoft.CSharp.dll 中发生了“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”类型的第一次机会异常
Microsoft.CSharp.dll 中发生了“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”类型的第一次机会异常
“ScratchConsoleApplication.vshost.exe”(托管 (v4.0.30319)):已加载“匿名托管 DynamicMethods 程序集”
Microsoft.CSharp.dll 中发生了“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”类型的第一次机会异常
Microsoft.CSharp.dll 中发生了“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”类型的第一次机会异常

任何尝试访问动态成员似乎都会向调试日志输出

RuntimeBinderException
。虽然我知道第一次机会异常本身并不是问题,但这确实给我带来了一些问题:

  1. 我经常将调试器设置为“异常时中断”,因为我正在编写 WPF 应用程序,否则所有异常最终都会转换为

    DispatcherUnhandledException
    ,并且您想要的所有实际信息都会丢失。 WPF 就这么烂。

  2. 一旦我点击任何使用

    dynamic
    的代码,调试输出日志就变得毫无用处。我关心的所有有用的跟踪线都隐藏在所有无用的
    RuntimeBinderException
    s

有什么办法可以关掉这个功能吗,或者不幸的是

RuntimeBinder
就是这样构建的?

谢谢,猎户座

c# exception dynamic
3个回答
31
投票

每当解析动态对象上的属性时,运行时都会尝试查找在编译时定义的属性。来自 DynamicObject doco:

您还可以添加自己的会员 从 DynamicObject 派生的类 班级。如果你的类定义了 属性,并且还覆盖 TrySetMember方法,动态 语言运行时 (DLR) 首先使用 语言绑定器寻找静态 类中属性的定义。 如果没有此类财产,DLR 调用 TrySetMember 方法。

每当运行时找不到静态定义的属性时,就会抛出

RuntimeBinderException
(即在 100% 静态类型的世界中会出现编译器错误)。来自MSDN文章

...RuntimeBinderException 代表一个 未能在某种意义上绑定 常见的编译器错误...

有趣的是,如果您使用

ExpandoObject
,则在尝试使用该属性时只会遇到一个异常:

dynamic bucket = new ExpandoObject();
bucket.SomeValue = 45;
int value = bucket.SomeValue; //<-- Exception here

也许

ExpandoObject
可以是替代方案?如果它不合适,您需要考虑实现
IDynamicMetaObjectProvider
,这就是
ExpandoObject
进行动态调度的方式。但是,它没有很好的记录,MSDN 建议您参阅 DLR CodePlex 以获取更多信息。


26
投票

这也困扰着我。 我将该例外添加到例外列表中,以便我可以取消选择它。 只需按照以下步骤操作:

  • 从“调试”菜单中,选择“异常”。
  • 单击右下角的“添加...”按钮。
  • 从类型下拉列表中选择“公共语言运行时异常”。
  • 键入“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”作为名称。
  • 单击“确定”。
  • 异常类型现在将出现在列表中。 只需取消选择即可。

我希望此设置可以跨解决方案保存,但我认为不能,因此您必须在每个解决方案上重新应用此设置。


0
投票

错误

'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll 
当 Csharp 尝试渲染未定义的模型对象时,

会在前端发生。你有两个选择。定义对象或将其从前端删除。我确信删除是防止此错误的更好选择,因为您无论如何都不会使用它,因为它未定义。这是一个例子;

后端

public SomeModel Index(){
    var model = new SomeModel{
        FirsName = "John"
    }
    return View(model)
}

前端

@model appname.Models.SomeModel

<div>@Model.FirstName</div>  //This wouldn't throw an error
<div>@Model.LastName</div>  //This would throw an error
© www.soinside.com 2019 - 2024. All rights reserved.