問題描述
我在 C# 中有一個標準的動態字典"類型類 -
class Bucket : DynamicObject{只讀字典<字符串,對象>m_dict = 新字典<字符串,對象>();public override bool TrySetMember(SetMemberBinder binder, object value){m_dict[binder.Name] = 值;返回真;}public override bool TryGetMember(GetMemberBinder binder, out object result){return m_dict.TryGetValue(binder.Name, out result);}}
現在我這樣稱呼它:
static void Main(string[] args){動態 d = new Bucket();d.Name = "獵戶座";//2個RuntimeBinderExceptionsConsole.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
.雖然我知道第一次機會異常本身并不是問題,但這確實給我帶來了一些問題:
當我正在編寫 WPF 應用程序時,我經常將調試器設置為異常中斷",否則所有異常最終都會轉換為
DispatcherUnhandledException
,而所有實際的你想要的信息丟失了.WPF 就是這么爛.只要我遇到任何使用
dynamic
的代碼,調試輸出日志就會變得毫無用處.我關心的所有有用的跟蹤行都隱藏在所有無用的RuntimeBinderException
s 中
有什么辦法可以關閉它,或者不幸的是 RuntimeBinder
就是這樣構建的?
謝謝,獵戶座
每當解析動態對象的屬性時,運行時都會嘗試查找在編譯時定義的屬性.來自 DynamicObject 文檔:
<塊引用>您也可以將自己的成員添加到從 DynamicObject 派生的類班級.如果您的班級定義屬性,并覆蓋TrySetMember 方法,動態語言運行時 (DLR) 首先使用尋找靜態語言的活頁夾類中屬性的定義.如果沒有這樣的屬性,DLR調用 TrySetMember 方法.
RuntimeBinderException
在運行時找不到靜態定義的屬性時拋出(即在 100% 靜態類型的世界中會出現編譯器錯誤).來自 MSDN 文章
...RuntimeBinderException 表示一個在某種意義上沒有約束力常見的編譯器錯誤...
有趣的是,如果您使用 ExpandoObject
,您在嘗試使用該屬性時只會遇到一個異常:
動態bucket = new ExpandoObject();桶.SomeValue = 45;int value = bucket.SomeValue;//<-- 這里例外
也許 ExpandoObject
可以替代?如果不合適,您需要考慮實施 IDynamicMetaObjectProvider
,這就是 ExpandoObject
進行動態調度的方式.但是,它的文檔記錄不是很好,MSDN 建議您參考 DLR CodePlex 了解更多信息.
I've got a standard 'dynamic dictionary' type class in 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);
}
}
Now I call it, as follows:
static void Main(string[] args)
{
dynamic d = new Bucket();
d.Name = "Orion"; // 2 RuntimeBinderExceptions
Console.WriteLine(d.Name); // 2 RuntimeBinderExceptions
}
The app does what you'd expect it to, but the debug output looks like this:
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
Any attempt to access a dynamic member seems to output a RuntimeBinderException
to the debug logs. While I'm aware that first-chance exceptions are not a problem in and of themselves, this does cause some problems for me:
I often have the debugger set to "break on exceptions", as I'm writing WPF apps, and otherwise all exceptions end up getting converted to a
DispatcherUnhandledException
, and all the actual information you want is lost. WPF sucks like that.As soon as I hit any code that's using
dynamic
, the debug output log becomes fairly useless. All the useful trace lines that I care about get hidden amongst all the uselessRuntimeBinderException
s
Is there any way I can turn this off, or is the RuntimeBinder
unfortunately just built like that?
Thanks, Orion
Whenever a property on a dynamic object is resolved, the runtime tries to find a property that is defined at compile time. From DynamicObject doco:
You can also add your own members to classes derived from the DynamicObject class. If your class defines properties and also overrides the TrySetMember method, the dynamic language runtime (DLR) first uses the language binder to look for a static definition of a property in the class. If there is no such property, the DLR calls the TrySetMember method.
RuntimeBinderException
is thrown whenever the runtime cannot find a statically defined property(i.e. what would be a compiler error in 100% statically typed world). From MSDN article
...RuntimeBinderException represents a failure to bind in the sense of a usual compiler error...
It is interesting that if you use ExpandoObject
, you only get one exception when trying to use the property:
dynamic bucket = new ExpandoObject();
bucket.SomeValue = 45;
int value = bucket.SomeValue; //<-- Exception here
Perhaps ExpandoObject
could be an alternative? If it's not suitable you'll need to look into implementing IDynamicMetaObjectProvider
, which is how ExpandoObject
does dynamic dispatch. However, it is not very well documented and MSDN refers you to the DLR CodePlex for more info.
這篇關于處理動態時拋出很多第一次機會 Microsoft.CSharp.RuntimeBinderExceptions的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!