У меня есть стандарт 'динамический словарь' класс типа в 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
Любая попытка получить доступ к динамическому участнику, кажется, производит a RuntimeBinderException
к журналам отладки. В то время как я знаю, что исключениями первого шанса не является проблема в и себя, это действительно вызывает некоторые проблемы для меня:
Мне часто устанавливали отладчик для "повреждения на исключениях", поскольку я пишу приложения WPF, и иначе все исключения заканчивают тем, что были преобразованы в a DispatcherUnhandledException
, и вся фактическая информация, которую Вы хотите, потеряна. WPF сосет как этот.
Как только я поразил любой код, это использует dynamic
, выходной журнал отладки становится довольно бесполезным. Все полезные соединительные линии, о которых я забочусь, скрыты среди всего бесполезного RuntimeBinderException
s
Есть ли любой способ, которым я могу выключить это или RuntimeBinder
к сожалению, просто созданный как этот?
Спасибо, Orion
Каждый раз, когда разрешается свойство динамического объекта, среда выполнения пытается найти свойство, определенное во время компиляции. Из 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
Возможно, ExpandoObject
может быть альтернатива? Если это не подходит, вам нужно будет изучить реализацию IDynamicMetaObjectProvider
, как ExpandoObject
выполняет динамическую диспетчеризацию. Однако он не очень хорошо документирован, и MSDN отсылает вас к DLR CodePlex за дополнительной информацией.