2012-04-06 10 views
11

Potrzebuję parametru atrybutu zmiany w czasie wykonywania. Uprościłem mój problem prostym przykładem.Zmiana parametru atrybutu niestandardowego w czasie wykonywania

klasa Atrybut:

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

Proste jednostka wich został urządzony właściwości z atrybutami:

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

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

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

Wartość nieruchomości na podmiot obiektu mogę zmienić z tej części kodu:

   entityProp.SetValue(entity,"NewData",null); 

ale nie wiem jak zmiana wartości atrybutu właściwości Name na obiekcie podmiotu

To nie działa:

attProp.SetValue(attribute,"NewData",null); 

Wartość propery Nazwa nadal jest oryginalny.

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

[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)); 
      } 
     } 



    } 

edycja: usunąć oryginalny post i dodał bardzo prostą jasną próbki. Niestety

+0

Nota boczna: dlaczego druga metoda łapie, a następnie rzuca wyjątek? –

Odpowiedz

10

Nie można zmienić atrybutów w czasie wykonywania. Są one osadzone w metadanych zgromadzenia. Twoja metoda zmienia stan wewnętrzny konkretnej instancji; ale po ponownym załadowaniu tego atrybutu otrzymujesz inną instancję.

+0

@Mike Dokładam wszelkich starań, aby znaleźć rozwiązanie umożliwiające zmianę atrybutów w środowisku wykonawczym. Nawet z moimi umiejętnościami 1337 haxxor nic nie znalazłem. Możesz nie lubić tej odpowiedzi, ale niestety jest to poprawne. – payo

+0

Masz rację, spędziłem jeden cały dzień, ale nie mogłem znaleźć rozwiązania, ponieważ ten problem nie ma rozwiązania. :(więc atrybuty area readonly? – Mike

3

Nie jest to możliwe z refleksją, ponieważ (jak już wspomniano) metadane zostały naprawione. 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 respektowane przez żaden kod używający odbicia, ale jakikolwiek kod używający TypeDescriptor (najczęściej kodującego dane i innego kodu UI) zauważy zmiany.

Uwaga TypDescriptor działa tylko z jednym typem każdego atrybutu na typ/element; atrybuty wielu instancji nie są dobrze obsługiwane.