2011-01-27 14 views
8

No estoy seguro de si es posible que he visto:
Change Attribute's parameter at runtime.
Mi caso es muy similar, pero estoy tratando de cambiar el atributo de una clase en tiempo de ejecución:Modificación característicos de las clases en tiempo de ejecución

[Category("Change me")] 
public class Classic 
{ 
    public string Name { get; set; } 
} 

Una de las respuestas fue:

Dim prop As PropertyDescriptor = TypeDescriptor 
    .GetProperties(GetType(UserInfo))("Age") 
Dim att As CategoryAttribute = DirectCast(
    prop.Attributes(GetType(CategoryAttribute)), 
    CategoryAttribute) 
Dim cat As FieldInfo = att.GetType.GetField(
    "categoryValue", 
     BindingFlags.NonPublic Or BindingFlags.Instance) 
cat.SetValue(att, "A better description") 

cambió a formato más legible, gracias a Marc Gravell:

TypeDescriptor.AddAttributes(table, new Category{ Name = "Changed" }); 

Todo es buena cuando se utiliza TypeDescriptor pero cuando se utiliza:

var attrs = (Category[])typeof(Classic).GetCustomAttributes(
    typeof(Category), 
    true); 
attrs[0].Name 

Nombre tiene el texto "Cambiar".
¿Hay alguna manera de cambiar este atributo en el tiempo de ejecución?

Editar:
necesito esto para Linq2Sql en el diseñador del código generado tiene el esquema de base de datos. Quiero utilizar el esquema predeterminado del usuario sin utilizar asignación XML o cambiar el código generado (la tabla todavía está en etapa de desarrollo y cambia con frecuencia).

El código del diseñador es:

[global::System.Data.Linq.Mapping.TableAttribute(Name="DbSchema.MyTable")] 
public partial class MyTable 

Quiero el atributo de ser:

[TableAttribute(Name="MyTable")] 

Ahora he excavado en el código de Marco y creo que utiliza linq2sql:

TableAttribute[] attrs = (TableAttribute[])typeof(MyTable) 
    .GetCustomAttributes(typeof(TableAttribute), true); 

Cuando uso TypeDescriptor para cambiar el atributo, el valor no se cambia en GetCustomAttributes.

+2

¿Por qué quieres hacer esto? Los atributos están destinados a proporcionar metadatos, no mucho más. ¿Por qué no tomar el enfoque de tener una "lista de reglas" que inicialmente está poblada por los atributos y cambia desde allí? – vcsjones

+0

¿Qué estás tratando de lograr? ¿Localizar texto en categoría? –

+0

@vcsjones lo crea o no, hay ocasiones en las que necesita agregar, cambiar o eliminar atributos en tiempo de ejecución. Tuve que hacerlo para agregar un convertidor a los enlaces de WPF para que se serializaran en lugar de evaluar. – Will

Respuesta

0

Si utiliza la reflexión , entonces no es como esto - reflexión atributos no pueden ser sustituidos - sólo el componente modelo vista se ve afectada por TypeDescriptor. Sin embargo, puede subclase CategoryAttribute para sus propósitos. Especialmente útil para i18n.

using System.ComponentModel; 
using System; 
[MyCategory("Fred")] 
class Foo { } 
static class Program 
{ 
    static void Main() 
    { 
     var ca = (CategoryAttribute)Attribute.GetCustomAttribute(typeof(Foo), typeof(CategoryAttribute)); 
     Console.WriteLine(ca.Category); 
       // ^^^ writes "I was Fred, but not I'm EVIL Fred" 
    } 
} 
class MyCategoryAttribute : CategoryAttribute 
{ 
    public MyCategoryAttribute(string category) : base(category) { } 
    protected override string GetLocalizedString(string value) 
    { 
     return "I was " + value + ", but not I'm EVIL " + value; 
    } 
} 
+0

Lamentablemente no puedo cambiar el atributo original ni crear mi propia versión. Linq2Sql espera TableAttribute. –

0

Debe codificar su atributo para que admita valores de tiempo de ejecución. Por ejemplo, los atributos de validación admiten la internacionalización de mensajes a través de la configuración de un tipo de recurso y una cadena de recursos en oposición a la cadena de mensajes estáticos.

Otro enfoque es utilizar un contenedor IOC como StructureMap o Unity para proporcionar algún objeto/servicio que proporcione los valores.

Si no desea vincular su atributo a un contenedor en particular, use el contenedor Common ServiceLocator proporcionado por el grupo de patrones y prácticas.

2

evitar la reflexión por completo, puede hacerlo a través de TypeDescriptor:

using System; 
using System.ComponentModel; 
using System.Linq; 
[Category("nice")] 
class Foo { } 
static class Program 
{ 
    static void Main() 
    { 
     var ca = TypeDescriptor.GetAttributes(typeof(Foo)) 
       .OfType<CategoryAttribute>().FirstOrDefault(); 
     Console.WriteLine(ca.Category); // <=== nice 
     TypeDescriptor.AddAttributes(typeof(Foo),new CategoryAttribute("naughty")); 
     ca = TypeDescriptor.GetAttributes(typeof(Foo)) 
       .OfType<CategoryAttribute>().FirstOrDefault(); 
     Console.WriteLine(ca.Category); // <=== naughty 
    } 
} 
+1

Bueno, realmente no funciona cada vez que uso TypeDescriptor obtengo el valor modificado. Pero linq2sql (para lo que necesito esto) usa (TableAttribute []) table.GetCustomAttributes (typeof (TableAttribute), true) que obtiene el valor original ... –

Cuestiones relacionadas