Pergunta sobre reflection, custom-attributes, c#, runtime – Alterar o parâmetro do atributo customizado no tempo de execução

12

Preciso de um parâmetro para alterar o atributo durante o tempo de execução. Eu simplifiquei meu problema para um exemplo simples.

Classe de atributo:

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

Entidade simples que decorou propriedades com atributos:

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

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

Eu criei a instância da classe MyEntity. Eu posso alterar o valor das propriedades do objeto, mas não posso alterar o valor da propriedade do atributo Name na entidade do objeto. É possível?

Valor da propriedade na entidade de objeto eu posso mudar com esta parte do código:

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

mas não sei como alterar o valor da propriedade do atributo Name on object entity

Isso não funciona:

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

Valor da propery O nome ainda é original.

Aqui está todo o código de teste. Obrigado pelo inferno.

<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: eu excluo a postagem original e adicionei uma amostra clara muito simples. Desculpa

Nota: por que o segundo método é pegar e depois lançar Exception? David Nelson

Sua resposta

2   a resposta
4

pois (como já foi observado) os metadados são fixos. É, no entanto, parcialmente possível com TypeDescriptor, que permite adicionar e substituir atributos em tempo de execução e fornecer modelos alternativos completos (TypeDescriptionProvider, etc). Essa abordagem não será respeitada por nenhum código que use reflexão, mas qualquer código que use o TypeDescriptor (mais comumente, vinculação de dados e outro código da interface do usuário) notará as alterações.

Nota TypeDescriptor só funciona realmente com um de cada tipo de atributo por typ / membro; os atributos de várias instâncias não são bem suportados.

11

rados nos metadados da montagem. Seu método está alterando o estado interno de uma instância específica; mas quando você carrega o atributo novamente, você está recebendo uma instância diferente.

Isso está totalmente errado. Vejo:stackoverflow.com/questions/51269/… Toastrackenigma
Você diz que não há como fazer isso, eu discordo, pois as respostas sobre essa outra questão que usa reflexão, etc, realmente funcionam para muitos desses casos - eles definitivamente resolveram o meu problema. Embora eu não discorde do fato de que os atributos fazem parte da montagem, discordo de, em linhas gerais, descartar a idéia de alterá-los em tempo de execução dizendo que é impossível, quando pelo menos em alguns casos há pelo menos maneiras de fazê-lo ( ou pelo menos algo queaparece como acontece), especialmente se puder resolver um problema como o do OP. Toastrackenigma
@Mike Fiz um grande esforço para encontrar uma solução para alterar atributos em tempo de execução. Mesmo com minhas habilidades de 1337 haxxor, não encontrei nada. Você pode não gostar desta resposta, mas infelizmente está correto. payo
Você está certo, passei um dia todo, mas não consegui encontrar solução, porque esse problema não tem solução. :( atributos área readonly? Mike
@Toastrackenigma não é "totalmente errado", ou qualquer outro tipo de erro, conforme demonstrado pelas respostas à pergunta que você vinculou. David Nelson

Perguntas relacionadas