Qual è il modo migliore per stabilire se un metodo è una proprietà all'interno di Policy Injection?

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

Domanda

Ho applicato un gestore personalizzato a una classe (utilizzando il Policy Injection Application Block in entlib 4) e vorrei sapere se il metodo di input è una proprietà quando viene chiamato Invoke.Di seguito è riportato l'aspetto del mio gestore.

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

Come puoi vedere dal mio esempio di codice, il modo migliore a cui ho pensato finora è stato analizzare il nome del metodo.Non c'è un modo migliore per farlo?

È stato utile?

Soluzione

Puoi anche verificare che IsSpecialName sia vero.questo sarà vero in una proprietà (tra le altre cose)

A livello il i metodi sono esposti come segue (utilizzando Environment.ExitCode come esempio):

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

Se volessi essere fantasioso potresti verificare dopo aver estratto il nome che detta proprietà esiste, ma ad essere onesti

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

così come inizia con get_ o set_, dovresti essere bravo anche con le persone che usano nomi sgradevoli (falsificare hidebysig è abbastanza facile, falsificare IsSpecialName sarebbe molto complicato)

Niente è garantito però.Qualcuno potrebbe emettere una classe con un metodo set_Foo che assomigliava proprio a un vero metodo set ma in realtà non era un set su una proprietà di sola lettura.A meno che non controlli se anche la proprietà CanRead/CanWrite.

Mi sembra una follia per te, anche se non ti aspetti un'elusione deliberata.Un semplice metodo di utilità/estensione su MethodInfo che seguisse questa logica non sarebbe troppo difficile e includere IsSpecialName quasi certamente coprirebbe tutte le tue esigenze.

Altri suggerimenti

Potresti controllare la proprietà IsSpecialName;sarà vero per i getter e i setter di proprietà.Tuttavia, sarà vero anche per altri metodi speciali, come gli sovraccarichi degli operatori.

Non ho familiarità con quel blocco dell'applicazione, ma presupponendo che la proprietà MethodBase sia di tipo System.Reflection.MethodBase, potresti dare un'occhiata alla proprietà IsSpecialName.

System.Reflection.MethodBase.IsSpecialName su MSDN

Un paio di voi hanno menzionato l'utilizzo della proprietà "IsSpecialName" del tipo MethodBase.Sebbene sia vero che restituirà true per la proprietà "gets" o "sets", restituirà true anche per gli sovraccarichi degli operatori come add_EventName oremove_EventName.Quindi dovrai esaminare altri attributi dell'istanza MethodBase per determinare se si tratta di una funzione di accesso alla proprietà.Sfortunatamente, se tutto ciò che hai è un riferimento a un'istanza MethodBase (che credo sia il caso dei comportamenti di intercettazione nel framework Unity) non esiste un vero modo "pulito" per determinare se si tratta di un setter o di un getter di proprietà.Il modo migliore che ho trovato è il seguente:

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

E' un po' tardi ma lo leggeranno anche gli altri.Oltre a IsSpecialName e al controllo del prefisso set_ (gli operatori hanno op_, evento subscr./remov.ha add_,remove_) puoi verificare se il metodo corrisponde a uno qualsiasi dei metodi di proprietà come questo:

    bool isProperty = method.ReflectedType.GetProperties().FirstOrDefault(p => 
        p.GetGetMethod().GetHashCode() == method.GetHashCode() 
        || p.GetSetMethod().GetHashCode() == method.GetHashCode())!=null;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top