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

时间:2010-06-02 01:55:37

标签: 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);
    }
}

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

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

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

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应用程序,否则所有异常最终都会转换为DispatcherUnhandledException,以及您想要的所有实际信息迷路了。 WPF很糟糕。

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

  3. 有什么办法可以解决这个问题,或者遗憾的是RuntimeBinder是不是就这样建了?

    谢谢,猎户座

2 个答案:

答案 0 :(得分:25)

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

  

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

只要运行时找不到静态定义的属性(即100%静态类型世界中的编译器错误),就会抛出

RuntimeBinderException。来自MSDN article

  

... RuntimeBinderException表示一个   在一个意义上没有约束力   通常的编译错误......

有趣的是,如果您使用ExpandoObject,则在尝试使用该属性时只会遇到一个例外:

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

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

答案 1 :(得分:21)

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

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

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