在处理动态时抛出了很多第一次机会Microsoft.CSharp.RuntimeBinderExceptions

Ori*_*rds 51 c# exception dynamic

我在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我打电话给它,如下:

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

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

A first chance exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll
A first chance exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll
'ScratchConsoleApplication.vshost.exe' (Managed (v4.0.30319)): Loaded 'Anonymously Hosted DynamicMethods Assembly'
A first chance exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll
A first chance exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in Microsoft.CSharp.dll

任何访问动态成员的尝试似乎都会输出RuntimeBinderException到调试日志.虽然我知道第一次机会异常本身并不是问题,但这确实会给我带来一些问题:

  1. 我经常将调试器设置为"中断异常",因为我正在编写WPF应用程序,否则所有异常最终都会转换为a DispatcherUnhandledException,并且您想要的所有实际信息都将丢失.WPF很糟糕.

  2. 一旦我点击任何正在使用的代码,dynamic调试输出日志就变得毫无用处.我关心的所有有用的跟踪线都隐藏在所有无用RuntimeBinderException的中

我有什么方法可以关闭它,或者RuntimeBinder不幸的是这样建造的?

谢谢,猎户座

Igo*_*aka 26

每当解析动态对象上的属性时,运行时都会尝试查找在编译时定义的属性.来自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
Run Code Online (Sandbox Code Playgroud)

也许ExpandoObject可以替代?如果它不合适,你需要考虑实现IDynamicMetaObjectProvider,这是ExpandoObject动态调度的方式.但是,它没有很好的文档记录,MSDN会将您引用到DLR CodePlex以获取更多信息.


Ant*_*ton 23

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

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

我希望这个设置可以在解决方案中保存,但我认为不可以,所以你必须在每个解决方案上重新应用这个设置.

  • 对我来说,这实际上并没有关闭显示异常的调试日志.它让我让调试器打破这些异常,但这不是我想要的.我希望他们停止喷涌. (10认同)
  • 在 Visual Studio 2015 中:调试菜单 -&gt; Windows -&gt; 异常设置 (Ctrl+Alt+E) (2认同)