Как лучше всего определить, является ли метод свойством внутри внедрения политики?
У меня есть собственный обработчик, примененный к классу (используя блок приложения Policy Injection в 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; }
}
Как вы можете видеть из моего примера кода, лучший способ, о котором я до сих пор думал, - это разбор имени метода. Разве нет лучшего способа сделать это?
5 ответов
Вы также можете проверить, что 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, который выглядит как метод реального набора, но на самом деле не является набором для свойства только для чтения. Если только вы не проверите, есть ли свойство CanRead/CanWrite.
Это кажется мне безумием для вас, хотя вы не ожидаете преднамеренного обхода. Простой метод утилиты / расширения в MethodInfo, который делал бы эту логику, не был бы слишком сложным, и включение IsSpecialName почти наверняка охватило бы все ваши потребности.
Некоторые из вас упоминали об использовании свойства IsSpecialName типа MethodBase. Несмотря на то, что true вернет true для свойства "gets" или "sets", оно также вернет true для перегрузок операторов, таких как add_EventName или remove_EventName. Поэтому вам нужно будет изучить другие атрибуты экземпляра MethodBase, чтобы определить, является ли он средством доступа к свойству. К сожалению, если все, что у вас есть, это ссылка на экземпляр MethodBase (который, как я считаю, имеет место при перехвате поведения в платформе Unity), то нет реального "чистого" способа определить, является ли он установщиком или получателем свойств. Лучший способ, который я нашел, заключается в следующем:
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_, событие subscr./remov. Имеет add_,remove_), вы можете проверить, совпадает ли метод с любым из методов свойств, таких как этот:
bool isProperty = method.ReflectedType.GetProperties().FirstOrDefault(p =>
p.GetGetMethod().GetHashCode() == method.GetHashCode()
|| p.GetSetMethod().GetHashCode() == method.GetHashCode())!=null;
Вы можете проверить свойство IsSpecialName; это будет верно для получателей и установщиков свойств. Однако это также будет справедливо для других специальных методов, таких как перегрузки операторов.
Я не знаком с этим блоком приложения, но предполагая, что свойство MethodBase имеет тип System.Reflection.MethodBase, вы можете взглянуть на свойство IsSpecialName.