Каков наилучший способ определить, является ли метод свойством из-за внедрения политики?
-
09-06-2019 - |
Вопрос
У меня есть пользовательский обработчик, примененный к классу (с использованием блока приложения для внедрения политики в entlib 4), и я хотел бы знать, является ли метод ввода свойством при вызове Invoke.Ниже показано, как выглядит мой обработчик.
[ConfigurationElementType(typeof(MyCustomHandlerData))]
public class MyCustomHandler : ICallHandler
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
if (input.MethodBase.IsPublic && (input.MethodBase.Name.Contains("get_") || input.MethodBase.Name.Contains("set_")))
{
Console.WriteLine("MyCustomHandler Invoke called with input of {0}", input.MethodBase.Name);
}
return getNext().Invoke(input, getNext);
}
public int Order { get; set; }
}
Как вы можете видеть из моего примера кода, лучший способ, о котором я до сих пор думал, - это синтаксический анализ имени метода.Разве нет лучшего способа сделать это?
Решение
Вы также можете проверить, что значение IsSpecialName равно true.это будет верно в свойстве (среди прочего)
На уровне il методы представлены следующим образом (используя Environment.ExitCode в качестве примера):
.method public hidebysig specialname static int32 get_ExitCode() cil managed
.method public hidebysig specialname static void set_ExitCode(int32 'value') cil managed
Если бы вы хотели пофантазировать, вы могли бы проверить после извлечения имени, что указанное свойство существует, но, честно говоря
if (m.IsSpecialName && (m.Attributes & MethodAttributes.HideBySig) != 0))
а также начинается с get_ или set_, тогда вы должны быть хороши даже для людей, использующих неприятные имена (подделать hidebysig достаточно просто, подделать IsSpecialName было бы очень сложно)
Однако ничто не гарантировано.Кто-то мог бы создать класс с методом set_Foo, который выглядел бы точно так же, как реальный метод set, но на самом деле не был set для свойства только для чтения.Если только вы не проверите, является ли свойство CanRead / CanWrite таким же.
Для вас это кажется мне безумием, хотя вы и не ожидаете преднамеренного обхода.Простая утилита / метод расширения в MethodInfo, которая выполняла бы эту логику, не была бы слишком сложной, и включение IsSpecialName почти наверняка покрыло бы все ваши потребности.
Другие советы
Вы могли бы проверить свойство IsSpecialName;это будет справедливо для получателей и установщиков свойств.Однако это также будет справедливо и для других специальных методов, таких как перегрузки оператора.
Я не знаком с этим прикладным блоком, но предполагая, что свойство MethodBase имеет тип System.Отражение.MethodBase , вы могли бы взглянуть на свойство IsSpecialName .
Пара из вас упомянула об использовании свойства "IsSpecialName" типа MethodBase.Хотя верно, что will возвращает true для свойства "gets" или "sets", оно также вернет true для перегрузок оператора, таких как add_EventName или remove_EventName .Таким образом, вам нужно будет изучить другие атрибуты экземпляра MethodBase, чтобы определить, является ли это средством доступа к свойству.К сожалению, если все, что у вас есть, это ссылка на экземпляр MethodBase (что, я полагаю, имеет место при перехвате поведения в Unity Framework), нет реального "чистого" способа определить, является ли это установщиком свойств или получателем.Лучший способ, который я нашел, заключается в следующем:
C#:
bool IsPropertySetter(MethodBase methodBase){
return methodBase.IsSpecialName && methodBase.Name.StartsWith("set_");
}
bool IsPropertyGetter(MethodBase methodBase){
return methodBase.IsSpecialName && methodBase.Name.StartsWith("get_");
}
VB:
Private Function IsPropertySetter(methodBase As MethodBase) As Boolean
Return methodBase.IsSpecialName AndAlso methodBase.Name.StartsWith("set_")
End Function
Private Function IsPropertyGetter(methodBase As MethodBase) As Boolean
Return methodBase.IsSpecialName AndAlso methodBase.Name.StartsWith("get_")
End Function
Немного поздно, но другие люди тоже это прочтут.В дополнение к IsSpecialName и проверке наличия префикса set_ (операторы имеют op_, event subscr./remov.имеет add_,remove_) вы можете проверить, соответствует ли метод какому-либо из методов свойств, подобных этому:
bool isProperty = method.ReflectedType.GetProperties().FirstOrDefault(p =>
p.GetGetMethod().GetHashCode() == method.GetHashCode()
|| p.GetSetMethod().GetHashCode() == method.GetHashCode())!=null;