Pytanie w sprawie custom-attributes, runtime, reflection, c# – Zmień parametr niestandardowego atrybutu w czasie wykonywania

12

Potrzebuję zmienić parametry atrybutu w czasie wykonywania. Uprościłem mój problem do prostego przykładu.

Klasa atrybutów:

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

Prosty element, który ozdobił właściwości atrybutami:

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

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

Stworzyłem instancję klasy MyEntity. Mogę zmienić wartość właściwości obiektu, ale nie mogę zmienić wartości właściwości atrybutu Nazwa na obiekcie. Czy to możliwe?

Wartość właściwości na obiekcie obiektu, którą mogę zmienić za pomocą tej części kodu:

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

ale nie zmieniam wartości właściwości atrybutu Nazwa na obiekcie

To nie działa:

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

Wartość oferty Nazwa jest nadal oryginalna.

Oto cały kod testowy. Dziękuję za piekło.

<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>

EDYCJA: Usuwam oryginalny post i dodałem bardzo prostą, przejrzystą próbkę. Przepraszam

Uwaga dodatkowa: dlaczego twoja druga metoda łapie, a następnie rzuca wyjątek? David Nelson

Twoja odpowiedź

2   odpowiedź
11

tadanych zespołu. Twoja metoda zmienia stan wewnętrzny określonej instancji; ale po ponownym załadowaniu atrybutu otrzymujesz inną instancję.

To jest złe. Widzieć:stackoverflow.com/questions/51269/… Toastrackenigma
Masz rację, spędziłem jeden dzień, ale nie mogłem znaleźć rozwiązania, ponieważ ten problem nie ma rozwiązania. :( tak atrybuty są tylko do odczytu? Mike
@Toastrackenigma nie jest „zwykłym błędem” lub jakimkolwiek innym błędem, jak pokazują odpowiedzi na pytanie, które powiązałeś. David Nelson
@Mike Włożyłem wiele wysiłku w znalezienie rozwiązania do zmiany atrybutów w czasie wykonywania. Nawet z moimi 1337 umiejętnościami haxxoru nie znalazłem nic. Odpowiedź może ci się nie podobać, ale niestety jest poprawna. payo
Powiedziałeś, że nie ma sposobu, aby to zrobić, nie zgadzam się, ponieważ odpowiedzi na to inne pytanie, które używają refleksji, itd., Rzeczywiście działają w wielu z tych przypadków - zdecydowanie rozwiązały mój problem. Chociaż nie zgadzam się z faktem, że atrybuty są częścią zespołu, nie zgadzam się z szerokim odrzuceniem idei zmiany ich w czasie wykonywania, mówiąc, że jest to niemożliwe, gdy przynajmniej w niektórych przypadkach istnieją przynajmniej sposoby na to ( lub przynajmniej coś takiegopojawia się tak jak to robi), zwłaszcza jeśli mogłoby to rozwiązać problem taki jak OP. Toastrackenigma
4

ponieważ (jak już wspomniano) metadane są poprawione. Jest to jednak częściowo możliwe dzięki TypeDescriptor, który umożliwia dodawanie i zastępowanie atrybutów w czasie wykonywania oraz dostarczanie kompletnych modeli alternatywnych (TypeDescriptionProvider, itp.). Podejście to nie będzie przestrzegane przez żaden kod, który używa odbicia, ale każdy kod wykorzystujący TypeDescriptor (najczęściej jest to powiązanie danych i inny kod UI) zauważy zmiany.

Uwaga: TypeDescriptor działa naprawdę tylko z jednym z każdego typu atrybutu na typ / element; atrybuty wielu instancji nie są dobrze obsługiwane.

Powiązane pytania