У меня есть собственный обработчик, примененный к классу (с использованием блока приложения для внедрения политики в 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; это будет верно для методов получения и установки свойств. Однако это также будет верно для других специальных методов, таких как перегрузки операторов.
Я не знаком с этим блоком приложения, но предполагая, что свойство MethodBase имеет тип System.Reflection.MethodBase, вы можете взглянуть на свойство IsSpecialName.
Вы также можете проверить, что IsSpecialName истинно. это будет верно для свойства (среди прочего)
На уровне 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. Хотя верно, что функция вернет истину для свойства «получает» или «устанавливает», она также вернет истину для перегрузок операторов, таких как 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;
Остерегайтесь: условие if также истинно для методов, которые добавляют или удаляют обработчики событий.