2011-12-11 9 views
17

Ho un C# un'annotazione che è:Come si inserisce un Func in un attributo C# (annotazione)?

[AttributeUsage(AttributeTargets.Method)] 
public class OperationInfo : System.Attribute { 
    public enum VisibilityType { 
     GLOBAL, 
     LOCAL, 
     PRIVATE 
    } 
    public VisibilityType Visibility { get; set; } 
    public string Title { get; set; } 
    public Func<List<string>, List<string>> Func; 

    public OperationInfo(VisibilityType visibility, string title, Func<List<string>, List<string>> function) { 
     Visibility = visibility; 
     Title = title; 
     Func = function; 
    } 
} 

Come si può vedere, c'è una proprietà che è un Funz e voglio chiamarla in modo dinamico. Fondamentalmente, vorrei analizzare tutti i metodi che hanno questa annotazione e quindi chiamare il Func associato all'annotazione.

mi piacerebbe usare in questo modo (questo è un semplice esempio di una funzione di eco, che ottiene una stringa e restituire la stessa stringa):

[OperationInfo(OperationInfo.VisibilityType.GLOBAL, "echo", IDoEcho)] 
    public static string DoEcho(string a) 
    { 
     return a; 
    } 

    [OperationInfo(OperationInfo.VisibilityType.PRIVATE, null, null)] 
    public static List<string> IDoEcho(List<string> param) { 
     return new List<string>() { DoEcho(param[0]) }; 
    } 

Non ho errore nel mio Classe di annotazione ma quando si tratta di rigenerare l'intera soluzione, ogni volta che dichiaro un metodo con l'annotazione, ho un errore che mi dice che devo usare letterali in un'annotazione.

Capisco che ci sono dei limiti, ma esiste un modo per evitare questo problema? So che posso usare una stringa invece di una Func, e guardare dinamicamente per la funzione il cui nome è lo stesso della stringa, ma mi piacerebbe non farlo.

Grazie per l'aiuto :)

+1

Potrebbe non sembrare bello, ma troverete spesso stringhe come argomenti agli attributi perché i valori devono essere noti al momento della compilazione. – danludwig

risposta

7

Non credo sia possibile, C# consente solo di utilizzare gli attributi con solo valori costanti.

Un modo per farlo sarebbe quello di creare una classe anziché una funzione, e quindi passare il tipo di quella classe all'attributo. Dovresti quindi istanziarlo con la reflection ed eseguire un metodo in esso.

Così Un esempio potrebbe essere:

public interface IDoStuff 
{ 
    IList<string> Execute(); 
} 

poi l'attributo vorrebbe un tipo al posto di un Funz

public OperationInfo(VisibilityType v, string title, Type type) 
{ 
    ///... 
} 

allora sarebbe creare una classe che implementa l'interfaccia e passarlo nel attributo. Anche se ciò significherebbe che (almeno inizialmente e senza conoscere il tuo problema) dovrai creare una nuova classe ogni volta che vuoi restituire risultati diversi.

6

Dalla C# spec:

17.1.3 tipi di parametri attributo

Le tipologie di parametri posizionali e nominato per una classe di attributi sono limitati ai tipi di parametri di attributo, che sono:

· Uno dei seguenti tipi: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.

· L'oggetto tipo.

· Il tipo System.Type.

· Un tipo di enum, a condizione che abbia accessibilità pubblica e che i tipi in cui è annidato (se presenti) dispongano anche di accessibilità pubblica (§17.2).

· Matrici unidimensionali dei tipi precedenti.

Problemi correlati