Это беспокоило меня долгое время, сегодня я нашел способ сделать это, используя деревья выражений в .NET 4.0.
Рассмотрим следующий код:
private class Borked
{
public object X
{
[DebuggerStepThrough]
get { throw new NotImplementedException(); }
}
}
private void SomeMethod()
{
var bad = new Borked();
object obj = bad.TryGet(o => o.X);
}
Сейчас -- Я могу вызывать этот код, не пропуская удар - единственное место, которое отладчик попытается остановить, находится в свойстве сломанного получателя Borked - поэтому я добавил туда атрибут DebuggerStepThrough
.
Вместо лямбды я беру дерево выражений (которое использует тот же синтаксис !!) и компилирую и запускаю его во время выполнения - это немного больше работы(едва), чем использование обычной лямбды, и она не будет работать для всех, но для простых запросов Linq и тому подобного она прекрасно работает.
Вся магия происходит в следующем методе - который, опять же,Первоначально использовался для принятия обычного аргумента Func<>
, но он приостанавливал отладчик при возникновении исключения (несмотря на атрибут step-through), поэтому теперь я делаю это с Expression<Func<>>
, например, так:
[DebuggerStepThrough]
public static T TryGet<OT, T>(this OT obj, params Expression<Func<OT, T>>[] getters)
{
T ret = default(T);
if (getters != null)
{
foreach (var getter in getters)
{
try
{
if (getter != null)
{
var getter2 = (Func<OT, T>)getter.Compile();
ret = getter2(obj);
break;
}
}
catch
{ /* try next getter or return default */ }
}
}
return ret;
}
Это верно - вы просто вызываете .Compile()
и приводите возвращаемое значение к обычному Func<>
, который вы можете немедленно вызвать !!- Насколько легко это было?!
В моей реализации я позволил пользователю передавать несколько параметров, чтобы у них был способ получить запасное значение (и чтобы это запасное значение только создавалось / оценивалось * 1022)* IF обязательно).
Кроме того, я не уверен, является ли причина подавления события отладки из-за VisualStudio «Просто мой код», или потому что он запускается встроенным в этом методе.... но в любом случае это чертовски хорошо работает, черт побери !!
Теперь я предполагаю, что вызов этого метода .Compile
для выражения во время выполнения не супер быстрый, но вНа практике это, похоже, не добавляет мне никакого снижения производительности в моих запросах.Итак, я очень взволнован (прошу прощения за множественные / избыточные удары и интеробанги и т. Д.)