2011-12-11 16 views
17

que tienen una anotación # C, que es:¿Cómo se pone un Func en un atributo C# (anotación)?

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

Como se puede ver, hay una propiedad que es un Func y que desea llamar de forma dinámica. Básicamente, me gustaría analizar todos los métodos que tienen esta anotación y luego llamar a Func binded a la anotación.

me gustaría utilizar de esta manera (esto es un ejemplo sencillo de una función de eco, que recibe una cadena y devolver la misma cadena):

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

tengo ningún error en mi Clase de anotación pero cuando se trata de regenerar toda la solución, cada vez que declaro un método con la anotación recibo un error que me dice que debo usar literales en una anotación.

Entiendo que hay limitaciones, pero ¿hay alguna manera de evitar este problema? Sé que puedo usar una cadena en lugar de una Func, y buscar dinámicamente la función cuyo nombre es el mismo que la cadena, pero me gustaría no hacerlo.

Gracias por ayudar :)

+1

Puede que no se vea bonito, pero a menudo encontrará cadenas como argumentos para los atributos porque los valores deben conocerse en tiempo de compilación. – danludwig

Respuesta

7

No creo que es posible, C# sólo se le permite usar sólo atributos con valores constantes.

Una forma de hacerlo sería crear una clase en lugar de un func, y luego pasar el tipo de esa clase en el atributo. Debería crear una instancia con reflejo y ejecutar un método en él.

lo tanto, un ejemplo sería:

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

entonces su atributo tomaría un tipo en lugar de un Func

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

, a continuación, podría crear una clase que implementa la interfaz y pasarlo a la atributo. Aunque esto significaría que (al menos inicialmente y sin conocer su problema) deberá crear una nueva clase cada vez que desee obtener resultados diferentes.

6

Desde el C# spec:

17.1.3 tipos de parámetros Attribute

Los tipos de parámetros posicionales y el nombre de una clase de atributo se limitan a los tipos de parámetros atributo, que son:

· Uno de los siguientes tipos: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.

· El tipo de objeto.

· El tipo System.Type.

· Un tipo de enumeración, siempre que tenga acceso público y los tipos en los que está anidado (si lo hay) también tienen acceso público (§17.2).

· Conjuntos unidimensionales de los tipos anteriores.

Cuestiones relacionadas