¿Cuál es la mejor manera de saber si un método es una propiedad desde la inyección de políticas?

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

Pregunta

Tengo un controlador personalizado aplicado a una clase (usando el bloque de aplicación de inyección de políticas en entlib 4) y me gustaría saber si el método de entrada es una propiedad cuando se llama a Invoke.A continuación se muestra cómo se ve mi controlador.

[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; }
}

Como puede ver en mi ejemplo de código, la mejor forma que se me ha ocurrido hasta ahora es analizando el nombre del método.¿No hay una mejor manera de hacer esto?

¿Fue útil?

Solución

También puedes comprobar que IsSpecialName es verdadero.esto será cierto en una propiedad (entre otras cosas)

En el nivel il, los métodos se exponen de la siguiente manera (usando Environment.ExitCode como ejemplo):

.method public hidebysig specialname static int32 get_ExitCode() cil managed
.method public hidebysig specialname static void set_ExitCode(int32 'value') cil managed

Si quisiera ser sofisticado, podría verificar después de extraer el nombre que dicha propiedad existe, pero para ser honesto

if (m.IsSpecialName && (m.Attributes & MethodAttributes.HideBySig) != 0)) 

además de comenzar con get_ o set_, entonces deberías ser bueno incluso para las personas que usan nombres desagradables (falsificar hidebysig es bastante fácil, falsificar IsSpecialName sería muy complicado)

Aunque nada está garantizado.Alguien podría emitir una clase con un método set_Foo que pareciera un método set real pero que en realidad no fuera un conjunto en una propiedad de solo lectura.A menos que verifique si la propiedad CanRead/CanWrite también.

Esto me parece una locura para usted, aunque no espera una elusión deliberada.Un método simple de utilidad/extensión en MethodInfo que hiciera esta lógica no sería demasiado difícil e incluir IsSpecialName casi con certeza cubriría todas sus necesidades.

Otros consejos

Puede comprobar la propiedad IsSpecialName;será cierto para los captadores y fijadores de propiedades.Sin embargo, también será válido para otros métodos especiales, como las sobrecargas de operadores.

No estoy familiarizado con ese bloque de aplicación, pero suponiendo que la propiedad MethodBase sea del tipo System.Reflection.MethodBase, podría echar un vistazo a la propiedad IsSpecialName.

System.Reflection.MethodBase.IsSpecialName en MSDN

Algunos de ustedes mencionaron el uso de la propiedad "IsSpecialName" del tipo MethodBase.Si bien es cierto que devolverá verdadero para la propiedad "obtiene" o "conjuntos", también devolverá verdadero para sobrecargas de operadores como add_EventName o remove_EventName.Por lo tanto, deberá examinar otros atributos de la instancia de MethodBase para determinar si es un descriptor de acceso a la propiedad.Desafortunadamente, si todo lo que tiene es una referencia a una instancia de MethodBase (que creo que es el caso de los comportamientos de interceptación en el marco de Unity), no existe una forma realmente "limpia" de determinar si se trata de un definidor o captador de propiedades.La mejor manera que he encontrado es la siguiente:

C#:

bool IsPropertySetter(MethodBase methodBase){
     return methodBase.IsSpecialName && methodBase.Name.StartsWith("set_");
}

bool IsPropertyGetter(MethodBase methodBase){
     return methodBase.IsSpecialName && methodBase.Name.StartsWith("get_");
}

V.B.:

 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

Es un poco tarde pero otras personas también leerán esto.Además de IsSpecialName y de comprobar el prefijo set_ (los operadores tienen op_, evento subscr./remov.tiene add_,remove_) puede verificar si el método coincide con cualquiera de los métodos de propiedades como este:

    bool isProperty = method.ReflectedType.GetProperties().FirstOrDefault(p => 
        p.GetGetMethod().GetHashCode() == method.GetHashCode() 
        || p.GetSetMethod().GetHashCode() == method.GetHashCode())!=null;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top