Pregunta

Me conseguí en una situación donde el uso de la clase System.Attribute parecía (a primera vista) para ser una buena idea.

Tengo un objeto que se desea imprimir en mi solicitud, y necesito una etiqueta antes de cada propiedad (o simplemente una cadena antes de ella). Podría poner cada propiedad hardcoded como:

Console.WriteLine("Color:"+obj.color);
Console.WriteLine("Size:"+obj.size);

Y así sucesivamente para cada propiedad. Pero en lugar de eso, yo estaba tratando de crear un código donde no se necesita esta 'etiqueta' que se hardcoded, por lo que podría imprimir cada propiedad dinámica.

Tengo algo por el estilo, utilizando la clase System.Attribute:

public class MyObject 
{
    [MyCustomLabel("Color:")]
    public string Color;

    [MyCustomLabel("Size:")]
    public string Size;
    //etc...
}

Así que aquí viene mi problema: recuperar el valor de este atributo no es imposible, pero no es agradable ya que tenía que utilizar un poco de reflexión para ello.

No estoy realmente miedo de utilizar la reflexión, pero parecía que estaba usando atributos de algo que no fue creada.

Me pregunto dónde están los mejores lugares para el uso de atributos, y si esto es realmente una situación para usarlo.

¿Fue útil?

Solución

Los atributos y la reflexión van de la mano. Con la excepción de algunos atributos del compilador / tiempo de ejecución, no hay manera de utilizarlos con el cabo que refleja sobre el código.

Dicho esto, su enfoque es razonable, y es posible que desee echar un vistazo a los atributos en la System.ComponentModel espacio de nombres que tienen un número de clases para decorar propiedades con metadatos útiles.

Otros consejos

Usted está en el camino correcto.

Además, no es un atributo [DisplayName] ya hecho a medida para este fin, que ha estado en .NET desde 2.0.

http://msdn.microsoft.com/en -us / biblioteca / system.componentmodel.displaynameattribute.aspx

Si acaba de escribir en la consola, es decir, su salida de estilo depuración entonces lo que quiere es mínima posibilidad de error tipográfico / copiar y pegar.

Esto es confuso bajo el capó, pero es muy eficaz en los sitios de llamada:

public static void WriteNameAndValue<T,TValue>(
    this TextWriter tw, T t,
    Expression<Func<T, TValue>> getter)
{
    var memberExpression = getter.Body as MemberExpression;
    if (memberExpression == null)
        throw new ArgumentException("missing body!");
    var member = memberExpression.Member;
    tw.Write(member.Name);
    tw.Write(": ");
    if (member is FieldInfo)
    {
        tw.Write(((FieldInfo)member).GetValue(t));
    }
    else if (member is PropertyInfo)
    {
        tw.Write(((PropertyInfo)member).GetValue(t, null));
    }
}


public static void WriteNameAndValueLine<T,TValue>(
    this TextWriter tw, T t,
    Expression<Func<T, TValue>> getter)
{

    WriteNameAndValue<T,TValue>(tw, t, getter);
    tw.WriteLine();
}

A continuación, se puede escribir

t.Foo = "bar";
t.Bar = 32.5;
Console.Out.WriteNameAndValueLine(t, x => x.Foo);
Console.Out.WriteNameAndValueLine(t, x => x.Bar);
// output
// Foo: bar
// Bar: 32.5

Si desea que esto sea más configurable en tiempo de ejecución a través de los recursos y con las consideraciones para la localización, puede hacerlo pero consideraría a otra, más estandarizado, el enfoque en su lugar si esto era un requisito probable.

P.S. si usted quiere conseguir la suposición podría reemplazar el interruptor FieldInfo / PropertyInfo con

tw.Write(getter.Compile()(t));

y entonces se podría comprobar si hay MethodInfo en la expresión, así (o permitir lambdas arbitrarias y sólo tiene que insertar el número de línea o algún otro texto genérico. No sugiero ir por este camino, el uso ya es confuso También esto puede causar no deseados cargar en lo que debería ser un método de registro simple.

Esto es exactamente cómo funciona la serialización, así que diría que su enfoque es razonable. Otra manera de abordar esto es para crear un diccionario de PropertyNames y sus títulos y luego buscar el título basado en el nombre de la propiedad.

  
    

Tengo un objeto a ser impreso en mi solicitud, y necesito una etiqueta antes de cada propiedad (o simplemente una cadena antes de ella).

  

¿Por qué piensa de la utilización de atributos en su caso? ¿Dónde se imprima este objetos de la aplicación.

Tal vez sólo aplicar ToString en su objeto (s)
Por ejemplo.

public override string ToString()
{
    StringBuilder sb = new StringBuilder();

    sb.Append("PropertyX: ");
    sb.AppendLine(this.PropertyX);

    // get string from resource file
    sb.Append(Resources.FileName);
    sb.Append(": ");
    sb.AppendLine(this.FileName);

    sb.Append("Number: ");
    sb.AppendLine(this.Number.ToString());

    return sb.ToString();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top