問(wèn)題描述
我在 C# 中有一個(gè)標(biāo)準(zhǔn)的動(dòng)態(tài)字典"類(lèi)型類(lèi) -
class Bucket : DynamicObject{只讀字典<字符串,對(duì)象>m_dict = 新字典<字符串,對(duì)象>();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);}}
現(xiàn)在我這樣稱(chēng)呼它:
static void Main(string[] args){動(dòng)態(tài) d = new Bucket();d.Name = "獵戶(hù)座";//2個(gè)RuntimeBinderExceptionsConsole.WriteLine(d.Name);//2個(gè)RuntimeBinderExceptions}
該應(yīng)用程序按照您的預(yù)期執(zhí)行,但調(diào)試輸出如下所示:
<上一頁(yè)>Microsoft.CSharp.dll 中出現(xiàn)了Microsoft.CSharp.RuntimeBinder.RuntimeBinderException"類(lèi)型的第一次機(jī)會(huì)異常Microsoft.CSharp.dll 中出現(xiàn)了Microsoft.CSharp.RuntimeBinder.RuntimeBinderException"類(lèi)型的第一次機(jī)會(huì)異常ScratchConsoleApplication.vshost.exe"(托管(v4.0.30319)):已加載匿名托管的 DynamicMethods 程序集"Microsoft.CSharp.dll 中出現(xiàn)了Microsoft.CSharp.RuntimeBinder.RuntimeBinderException"類(lèi)型的第一次機(jī)會(huì)異常Microsoft.CSharp.dll 中出現(xiàn)了Microsoft.CSharp.RuntimeBinder.RuntimeBinderException"類(lèi)型的第一次機(jī)會(huì)異常任何 訪問(wèn)動(dòng)態(tài)成員的嘗試似乎都會(huì)向調(diào)試日志輸出 RuntimeBinderException
.雖然我知道第一次機(jī)會(huì)異常本身并不是問(wèn)題,但這確實(shí)給我?guī)?lái)了一些問(wèn)題:
當(dāng)我正在編寫(xiě) WPF 應(yīng)用程序時(shí),我經(jīng)常將調(diào)試器設(shè)置為異常中斷",否則所有異常最終都會(huì)轉(zhuǎn)換為
DispatcherUnhandledException
,而所有實(shí)際的你想要的信息丟失了.WPF 就是這么爛.只要我遇到任何使用
dynamic
的代碼,調(diào)試輸出日志就會(huì)變得毫無(wú)用處.我關(guān)心的所有有用的跟蹤行都隱藏在所有無(wú)用的RuntimeBinderException
s 中
有什么辦法可以關(guān)閉它,或者不幸的是 RuntimeBinder
就是這樣構(gòu)建的?
謝謝,獵戶(hù)座
每當(dāng)解析動(dòng)態(tài)對(duì)象的屬性時(shí),運(yùn)行時(shí)都會(huì)嘗試查找在編譯時(shí)定義的屬性.來(lái)自 DynamicObject 文檔:
<塊引用>您也可以將自己的成員添加到從 DynamicObject 派生的類(lèi)班級(jí).如果您的班級(jí)定義屬性,并覆蓋TrySetMember 方法,動(dòng)態(tài)語(yǔ)言運(yùn)行時(shí) (DLR) 首先使用尋找靜態(tài)語(yǔ)言的活頁(yè)夾類(lèi)中屬性的定義.如果沒(méi)有這樣的屬性,DLR調(diào)用 TrySetMember 方法.
RuntimeBinderException
在運(yùn)行時(shí)找不到靜態(tài)定義的屬性時(shí)拋出(即在 100% 靜態(tài)類(lèi)型的世界中會(huì)出現(xiàn)編譯器錯(cuò)誤).來(lái)自 MSDN 文章
...RuntimeBinderException 表示一個(gè)在某種意義上沒(méi)有約束力常見(jiàn)的編譯器錯(cuò)誤...
有趣的是,如果您使用 ExpandoObject
,您在嘗試使用該屬性時(shí)只會(huì)遇到一個(gè)異常:
動(dòng)態(tài)bucket = new ExpandoObject();桶.SomeValue = 45;int value = bucket.SomeValue;//<-- 這里例外
也許 ExpandoObject
可以替代?如果不合適,您需要考慮實(shí)施 IDynamicMetaObjectProvider
,這就是 ExpandoObject
進(jìn)行動(dòng)態(tài)調(diào)度的方式.但是,它的文檔記錄不是很好,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.
這篇關(guān)于處理動(dòng)態(tài)時(shí)拋出很多第一次機(jī)會(huì) Microsoft.CSharp.RuntimeBinderExceptions的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!