Pregunta sobre reflection, custom-attributes, c#, runtime – Cambiar el parámetro del atributo personalizado en tiempo de ejecución

12

Necesito cambiar el parámetro del atributo durante el tiempo de ejecución. Simplifiqué mi problema al ejemplo simple.

Clase de atributo:

<code>    [AttributeUsage(AttributeTargets.Property)]
    public class MyAttribute : Attribute
    {
        public string Name { get; set; }
    }
</code>

Entidad simple que ha decorado propiedades con atributos:

<code>    public class MyEntity
    {
        [MyAttribute(Name="OldValue1")]
        public string Data1{ get; set; }

        [MyAttribute(Name = "OldValue2")]
        public string Data2 { get; set; }
    }
</code>

He creado la instancia de la clase MyEntity. Puedo cambiar el valor de las propiedades del objeto, pero no puedo cambiar el valor de la propiedad del atributo Nombre en la entidad del objeto. ¿Es posible?

El valor de la propiedad en la entidad de objeto que puedo cambiar con esta parte del código:

<code>                entityProp.SetValue(entity,"NewData",null);
</code>

pero no sé cómo cambiar el valor de la propiedad del atributo Nombre en la entidad objeto

Esto no funciona:

<code>attProp.SetValue(attribute,"NewData",null);
</code>

Valor de la propiedad El nombre sigue siendo original.

Aquí está todo el código de prueba. Gracias por hellp.

<code>    [TestMethod]
    public  void Test()
    {
        var entity = new MyEntity
                         {
                             Data1 = "OldData",
                             Data2 = "OldData"
                         };

        PropertyInfo[] entityProps = entity.GetType().GetProperties();

        foreach (var entityProp in entityProps)
        {
            var attribute = Attribute.GetCustomAttribute(entityProp, typeof (MyAttribute)) as MyAttribute;

            if (attribute != null)
            {
                //get attribute’s property NAME
                PropertyInfo attProp= attribute.GetType().GetProperty("Name");

                //get entity property value
                var propertyValue = entityProp.GetValue(entity, null);

                //get attribute’s property NAME value
                var atributeNameValue = attProp.GetValue(entity, null);

                TestContext.WriteLine(string.Format("property name:{0} property value: {1} : atribute name value: {2}\n", 
                    entityProp.Name, propertyValue, atributeNameValue)); 

                //change values
                entityProp.SetValue(entity,"NewData",null);

                //how can I change value of property Name on object entity ?
                attProp.SetValue(attribute,"NewData",null);

            }

        }

        TestContext.WriteLine(string.Format("After change\n"));

        foreach (var entityProp in entityProps)
        {
            var attribute = Attribute.GetCustomAttribute(entityProp, typeof(MyAttribute)) as MyAttribute;

            if (attribute != null)
            {

                PropertyInfo attProp = attribute.GetType().GetProperty("Name");

                var propertyValue = entityProp.GetValue(entity, null);
                var atributeNameValue = attProp.GetValue(entity, null);

                TestContext.WriteLine(string.Format("property name:{0} property value: {1} : atribute name value: {2}\n",
                    entityProp.Name, propertyValue, atributeNameValue));
            }
        }



    }
</code>

EDITADO: elimino la publicación original y agregué una muestra clara muy simple. Lo siento

Nota al margen: ¿por qué tu segundo método atrapa y luego lanza Excepción? David Nelson

Tu respuesta

2   la respuesta
11

No puede cambiar los atributos en tiempo de ejecución. Están incrustados en los metadatos del conjunto. Su método está cambiando el estado interno de una instancia particular; pero cuando vuelve a cargar el atributo, está obteniendo una instancia diferente.

Usted simplemente dice que no hay manera de hacer esto, no estoy de acuerdo, ya que las respuestas a esa otra pregunta que utiliza la reflexión, etc., realmente funcionan para muchos de estos casos; definitivamente resolvieron mi problema. Si bien no estoy en desacuerdo con el hecho de que los atributos son parte del conjunto, no estoy de acuerdo con rechazar la idea de cambiarlos en tiempo de ejecución al decir que es imposible, cuando al menos en algunos casos hay al menos formas de hacerlo ( o al menos algo queaparece como lo hace), especialmente si pudiera resolver un problema como OP's. Toastrackenigma
Esto es simplemente un error. Ver:stackoverflow.com/questions/51269/… Toastrackenigma
@Mike Puse mucho esfuerzo en encontrar una solución para cambiar los atributos en tiempo de ejecución. Incluso con mis habilidades de 1337 haxxor, no encontré nada. Puede que no te guste esta respuesta, pero desafortunadamente es correcta. payo
@Toastrackenigma no está "simplemente equivocado", o cualquier otro tipo de error, como lo demuestran las respuestas a la pregunta que vinculó. David Nelson
Tiene razón, pasé uno todo el día pero no pude encontrar una solución porque este problema no tiene solución. :( ¿entonces los atributos son solo de lectura? Mike
4

Esto no es posible con la reflexión, ya que (como ya se mencionó) los metadatos son fijos. Sin embargo, es parcialmente posible con TypeDescriptor, que permite agregar y reemplazar atributos en tiempo de ejecución y proporcionar modelos alternativos completos (TypeDescriptionProvider, etc.). Este código no será respetado por ningún código que use reflexión, pero cualquier código que use TypeDescriptor (generalmente, el enlace de datos y otro código de UI) notará los cambios.

Nota TypeDescriptor solo funciona con uno de cada tipo de atributo por tipo / miembro; Los atributos de varias instancias no están bien soportados.

Preguntas relacionadas