处理dynamic时引发大量的Microsoft.CSharp.RuntimeBinderExceptions

我在C#中有一个标准的“dynamic词典”types的类 –

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 } 

该应用程序做你所期望的,但debugging输出如下所示:

在Microsoft.CSharp.dll中发生第一次机会exception的typesMicrosoft.CSharp.RuntimeBinder.RuntimeBinderException
在Microsoft.CSharp.dll中发生第一次机会exception的typesMicrosoft.CSharp.RuntimeBinder.RuntimeBinderException
 'ScratchConsoleApplication.vshost.exe'(托pipe(v4.0.30319)):加载“匿名托pipe的DynamicMethods程序集”
在Microsoft.CSharp.dll中发生第一次机会exception的typesMicrosoft.CSharp.RuntimeBinder.RuntimeBinderException
在Microsoft.CSharp.dll中发生第一次机会exception的typesMicrosoft.CSharp.RuntimeBinder.RuntimeBinderException

任何尝试访问dynamic成员似乎RuntimeBinderException向debugging日志输出一个RuntimeBinderException 。 虽然我意识到一次机会的例外本身并不是一个问题,但这确实会给我带来一些问题:

  1. 我经常会将debugging器设置为“打破exception”,因为我正在编写WPF应用程序,否则所有exception最终都会转换为DispatcherUnhandledException ,并且所有您想要的实际信息都将丢失。 WPF就是这样的。

  2. 只要我点击任何使用dynamic代码,debugging输出日志就变得毫无用处。 我所关心的所有有用的trace行都隐藏在所有无用的RuntimeBinderException

有没有什么办法可以关掉它,或者不幸的是, RuntimeBinder就是这样构build的?

谢谢,猎户座

只要parsingdynamic对象上的属性,运行时就会尝试查找在编译时定义的属性。 来自DynamicObject doco:

您也可以将您自己的成员添加到从DynamicObject类派生的类中。 如果您的类定义了属性并覆盖了TrySetMember方法,那么dynamic语言运行库(DLR)首先使用语言联编程序来查找类中属性的静态定义。 如果没有这样的属性,则DLR调用TrySetMember方法。

如果运行时无法find一个静态定义的属性(例如100%静态types的世界中的编译器错误),则会引发RuntimeBinderException 。 从MSDN文章

RuntimeBinderException表示在通常的编译器错误意义上的绑定失败…

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

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

也许ExpandoObject可以替代? 如果它不合适,你需要考虑实现IDynamicMetaObjectProvider ,这是ExpandoObject如何dynamic分派的。 但是,它没有很好的logging,MSDN将您引用到DLR CodePlex以获取更多信息。

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

  • 从debugging菜单中select例外。
  • 点击右下angular的“添加…”button。
  • 从Type下拉菜单中select“Common Language Runtime Exceptions”。
  • 键入“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”作为名称。
  • 点击OK。
  • 现在,列表中将显示例外types。 只需取消select它。

我希望这个设置可以保存在不同的解决scheme中,但我不认为它可以,所以你将不得不在每个解决scheme上重新应用这个设置。