2013-07-30 374 views
5

我的CTO(首席技術官)要求我想出一種方法,他可以在基類中編寫一個函數,並且可以訪問所有屬性孩子班。以下是我想出了 -通過父類中的函數訪問子類屬性

基類

class Assets 
{ 
    public Assets getPropertyVal(Assets asObj) 
    { 
     PropertyInfo[] propInfos = asObj.GetType().GetProperties(); 
     string strAttributeValue = "10"; 
     foreach (PropertyInfo propInfo in propInfos) 
     { 
      // Getting the value 
      var propValue = propInfo.GetValue(asObj, null); 

      // Setting the value 
      propInfo.SetValue(asObj, Convert.ChangeType(strAttributeValue, propInfo.PropertyType), null); 

     } 
     return asObj; 
    } 
} 

子類

class House : Assets 
{ 
    public int rooms{get; set;} 
} 

Program.cs的文件

class Program 
{ 
    static void Main(string[] args) 
    { 
     House hsObj = new House(); 
     hsObj.rooms = 5; 

     Assets asObj = hsObj.getPropertyVal(hsObj); 
     // Returns asObj as JSON 
    } 
} 

現在這工作正常,但我只是想知道是否有更好的方式在C#中執行此操作。

請注意,我們不知道什麼屬性會出現在子類中,所以這將不得不在運行時確定。

UPDATE這就很清楚,我只是想知道是否有更好的方式來訪問子類的屬性,一個沒有使用反射。重要的一點是,我們不知道兒童班可能擁有什麼樣的特性。

UPDATE#2:我正在使用一個有許多實體的產品。這些實體具有不同的屬性。我希望能夠在一個地方訪問和使用所有這些屬性。這個功能就是這樣。這就是我可以訪問所有數據的一個地方。

+1

在您的示例中,您將創建一個對象並獲取該對象的所有屬性,然後在該對象中設置相同的屬性。它看起來像這樣:var propValue = asObj.rooms; asObj.rooms =(int)propValue;'。你想要什麼?你是否想要將所有屬性從子類複製到基類? –

+0

@VyacheslavVolkov,我只是想知道是否有更好的方式來訪問子類的屬性而不使用反射。 –

+0

我不明白這個的目的。在你的例子中,你用'Console.WriteLine(hsObj.rooms);'硬編碼子屬性名稱。你也可以完全擺脫'hsObj =(House)hsObj.getPropertyVal(hsObj);'行。反射被完全浪費了。你能想出一個你想要完成的更好的例子嗎? – Dan

回答

5

首先,你的Program.cs並不真正「做」你說你想要的東西。這聽起來像你想要一個程序,這樣你就可以做到這一點:

Asset myAsset = new House(); 
myAsset.Rooms = 5; 

但是,爲什麼你甚至想要這樣做呢?如果你的資產是不是房子,它會拋出一個異常,所以你需要檢查第一:

if (myAsset is House) 
    myAsset.Rooms = 5; 

在這一點上,你可能也只是將它轉換爲房子雖然。這聽起來像你可能想要使用PropertyBag或字典而不是繼承。

我想你所描述的是這個。請注意,選項1並沒有真正限制哪些類可以使用哪些屬性,所以我猜這不適用於您的特定情況。

// Option 1, a Property Bag (Note: this replaces the properties on the classes) 
class Asset 
{ 
    Dictionary<string, object> myPropertyBag = new Dictionary<string, object>(); 

    public T GetProperty<T>(string property) 
    { 
     // This throws if the property doesn't exist 
     return (T)myPropertyBag[property]; 
    } 

    public void SetProperty<T>(string property, T value) 
    { 
     // This adds the property if it doesn't exist 
     myPropertyBag[property] = (object)value; 
    } 
} 

// Option 2, use a switch and override this function in derived classes 
class Asset 
{ 
    public int SomePropertyOnAsset { get; set; } 

    public virtual T GetProperty<T>(string property) 
    { 
     switch (property) 
     { 
      case "SomePropertyOnAsset": return this.SomePropertyOnAsset; 

      default: throw new ArgumentException("property"); 
     } 
    } 

    public virtual void SetProperty<T>(string property, T value) 
    { 
     switch (property) 
     { 
      case "SomePropertyOnAsset": this.SomePropertyOnAsset = (int)value; 

      default: throw new ArgumentException("property"); 
     } 
    } 
} 

class House : Asset 
{ 
    public int Rooms { get; set; } 

    public virtual T GetProperty<T>(string property) 
    { 
     switch (property) 
     { 
      case "Rooms": return this.Rooms; 

      default: return base.GetProperty<T>(property); 
     } 
    } 

    public virtual void SetProperty<T>(string property, T value) 
    { 
     switch (property) 
     { 
      case "Rooms": this.Rooms = (int)value; 
       break; 

      default: base.SetProperty<T>(property, value); 
       break; 
     } 
    } 
} 

那麼,這是你如何使用它們:

// Option 1 
Asset asset = new House(); 
asset.SetProperty("Rooms", 5); 
var rooms = asset.GetProperty<int>("Rooms"); 

// Option 2 
Asset asset = new House(); 
asset.SetProperty("Rooms", 5); 
asset.SetProperty("SomePropertyOnAsset", 10); 
asset.SetProperty("SomethingElse", 15); // Throws ArgumentException 

一個第三選擇是使資產一DynamicObject。 http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx

如果您不能或不想對您的資產基類或觸摸每個實體進行重大更改,則可能需要使用反射。

+0

檢查我的更新。 –

+0

感謝DynamicObject類似乎很有趣。 –

1

盧克·格拉維特可能是對的。你可能只想把它扔到房子裏。

House myHouse = asObj as House; 
if (myHouse != null) 
{ 
    // do some fun house stuff 
} 

Yacht myYacht = asObj as Yacht; 
if (myYacht != null) 
{ 
    // put on monocle 
} 
+0

爲我工作。謝謝! – Willy