2012-04-06 36 views
11

我需要在運行時更改屬性的參數。我簡化了我的問題到簡單的例子。在運行時更改自定義屬性的參數

屬性類:

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

簡單的實體至極擁有裝飾性與屬性:

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

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

我創建的類myEntity所的instace。我可以改變對象屬性的值,但是我不能改變對象實體的屬性名稱的值。可能嗎?

值對對象實體屬性我可以用這部分代碼更改:

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

但我不改變屬性的屬性名稱如何價值的對象實體

這不行:

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

值屬性格式名稱的仍然是原來的。

這裏是所有測試代碼。謝謝你,hellp。

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



    } 

編輯:我刪除原帖,並添加非常簡單明確的樣本。對不起

+0

附註:爲什麼你的第二個方法捕獲然後拋出異常? – 2012-04-06 18:03:59

回答

10

你不能在運行時改變屬性。它們嵌入到程序集的元數據中。你的方法正在改變特定實例的內部狀態;但是當你再次加載屬性時,你會得到一個不同的實例。

+0

@Mike我花了很多精力找到一個解決方案來在運行時改變屬性。即使我的1337哈克斯技能,我什麼也沒找到。你可能不喜歡這個答案,但不幸的是它是正確的。 – payo 2012-04-06 18:09:13

+0

你是對的我整天呆了一天,但找不到解決方案,因爲這個問題沒有解決方案。 :(所以屬性區域只讀? – Mike 2012-04-06 18:13:31

3

這是不可能的反射,因爲(如已經提到的)元數據是固定的。但是,TypeDescriptor可以部分實現,它允許在運行時添加和替換屬性,並提供完整的替代模型(TypeDescriptionProvider等)。任何使用反射的代碼都不會考慮這種方法,但任何使用TypeDescriptor的代碼(通常是數據綁定和其他UI代碼)都會注意到這些更改。

注意TypeDescriptor只能用於每個類型/成員的每個屬性類型之一;多實例屬性得不到很好的支持。