Обходной путь для MethodBase.GetCurrentMethod () в Compact Framework 3.5

Я хочу использовать Linq IQueryable Toolkit в проекте на .NET Compact Framework. Возможности Linq в CF немного изменены, то есть: интерфейс IQueryable недоступен. Итак, я нашел сторонние библиотеки, которые реализуют недостающие функции, которые мне нужны.

Теперь у меня проблема с отсутствующим методом "MethodBase.GetCurrentMethod ()". Существует около 100 методов, в которых используется этот метод. Так что мне не нужен точный клон GetCurrentMethod (). Обходного пути для этого конкретного случая достаточно.

Образец исходного кода:

public static bool Any<TSource>( this IQueryable<TSource> source ) {
    return source.Provider.Execute<bool>( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod( new Type[] { typeof( TSource ) } ), new Expression[] { source.Expression } ) );
}

public static bool Any<TSource>( this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate ) {
    return source.Provider.Execute<bool>( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod( new Type[] { typeof( TSource ) } ), new Expression[] { source.Expression, Expression.Quote( predicate ) } ) );
}

Возможное решение - заменить "(MethodInfo) MethodBase.GetCurrentMethod ()" конкретным вызовом метода. Например: GetMethod_Any_TSource_On_Source () и GetMethod_Any_TSource_On_Source_With_Predicate_TSource_Bool ().

Я ищу какое-нибудь удобное решение, как это решить.


person TcKs    schedule 12.03.2009    source источник


Ответы (1)


См. это обсуждение

Это практически невозможно в простом управляемом коде в Compact Framework 1.0.

В версии 2.0 это возможно, но подвержено ошибкам, ненадежно и, что наиболее важно, НЕ гарантирует правильность (серьезный недостаток).

Я бы предложил вместо этого написать макрос, который может найти все экземпляры «((MethodInfo) MethodBase.GetCurrentMethod ())» и определить метод, в котором они находятся.

Просто конвертирую каждую строку вот так

".*\(\(MethodInfo\)MethodBase\.GetCurrentMethod\(\)\).*"

создать новое исключение ((MethodInfo) MethodBase.GetCurrentMethod ()). Name);

  • Скомпилировать для некомпактной структуры (исправляя вручную места, которые заменяет регулярное выражение, их не должно быть много)
  • Запустите все методы в классах, в которых произошла замена путем отражения.
  • перехватить возникшие исключения и распечатать сообщение (имя метода) и первую строку трассировки стека.

Затем это дает вам список того, что вам нужно вставить непосредственно в каждый сайт вызова (вероятно, подкрепленный лениво созданным статическим полем, содержащим MethodInfo для каждого из них.

Это громоздко, но может работать достаточно хорошо как разовое предварительное обновление фреймворка, хотя, честно говоря, это может быть так же быстро, как и вручную.

person ShuggyCoUk    schedule 22.04.2009
comment
+1 Большое спасибо за ответ. На самом деле я переписал все .GetCurrentMethod как ((Func ‹T1, T2, ...›)% TypeName%.% MethodName%). Method. Было проделано много работы, но производительность лучше, чем при вызове .GetCurrentMethod, и он работает. Мне повезло, что я потребовал использовать его только в статических методах, поэтому переписать его было не так сложно. Способ с генерацией исключения действительно неудобен и убивает производительность, если его часто используют. Но спасибо за предложение. - person TcKs; 23.04.2009
comment
Круто, вы это делали вручную или с помощью инструмента? Если с помощью инструмента, возможно, вы могли бы добавить это в качестве ответа (и принять его), так как это было бы полезно другим. - person ShuggyCoUk; 23.04.2009
comment
Я делал это вручную, потому что в классах и методах много использовались дженерики. Собственно я это уже почти сделал, как вы писали. Хорошо, я могу принять твой ответ. - person TcKs; 23.04.2009
comment
Хорошо, спасибо, если у вас есть какая-либо информация или рекомендации, не стесняйтесь редактировать мой ответ, как вам нравится. - person ShuggyCoUk; 23.04.2009