Каков наилучший способ определить, является ли метод свойством из-за внедрения политики?

StackOverflow https://stackoverflow.com/questions/73467

Вопрос

У меня есть пользовательский обработчик, примененный к классу (с использованием блока приложения для внедрения политики в 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 в MSDN

Пара из вас упомянула об использовании свойства "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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top