2013-03-22 88 views
1

我通過用戶界面即時創建節點列表。在我的列表中,我可以通過反射來實例化這些對象,從而根據下面的類結構向List中添加任意數量的對象(AAA,BBB等)。訪問派生類中的字段

public abstract class Node : IDisposable 
{ 
    protected int x; 
} 
public class AAA : Node 
{ 
    public int iA; 
} 
public class BBB : Node 
{ 
    public int iB; 
} 

創建列表後,我想訪問派生對象中的擴展字段。我知道我不得不沮喪地訪問擴展字段,但爲了做到這一點,我必須執行一個明確的演員。

foreach (Node nn in MyList)     //assume the first node in the list is AAA 
{ 
    int m = ((namespace.AAA) nn).iA;   //this works 
    int n = (AAA) nn).iA;      //this works 
} 

我想知道如果我可以使用字符串來創建實際的downcast。也許它不能完成。也許我錯過了一些東西。我想做什麼不工作將是類似於以下內容。

foreach (Node nn in MyList)  //assume the first node in the list is AAA 
{ 
    Type t2 = nn.GetType();  //{Name = AAA; FullName = namespace.AAA} (*debugger*) 
    string str = t2.FullName;  //namespace.AAA 

    int m = ((str) nn).iA;   //this DOESN'T work 
} 

當我在調試器中查看nn的值時,FullName表示我想用於downcast的類。

我可以通過使用switch語句來解決這個問題,該語句基於代表cast類語句中的類和硬代碼的字符串,但由於我有超過100個不同的節點,我將在未來添加更多的節點,每次添加節點時都要修改switch語句。如果可能的話,我寧願不這樣做。

在此先感謝您的任何回覆。

感謝Douglas指出我可以使用FieldInfo來獲取iA的值。我只想在這個話題上多做一點。如果我想採用AAA類並通過組合擴展它,我也可以通過FieldInfo訪問這些類中的字段。

public class AAA : Node 
{ 
    public int iA; 
    public X[] XArray; //where X is some other random class with pubic fields 
    public Y[] YArray; //where Y is some other abstract class 
} 
+0

http://stackoverflow.com/questions/493490/converting-a-string-to-a-class-name – box86rowh 2013-03-22 17:17:09

+0

這看起來像泛型的完美使用,但要說更多將需要看到更多的你的應用程序使用 – 2013-03-22 17:22:23

+0

您是否仍然需要switch語句來知道您是否正在尋找類型爲BBB的AAA或iB型屬性iA? – 2013-03-22 17:27:32

回答

0

你在做什麼似乎是在你的設計中某個地方出現錯誤想法的產物。

爲什麼基類節點沒有在AAA或BBB的構造函數中設置的稱爲iNodeImplementation的屬性,而不是在類中使用iA和iB?那麼你不必做所有這些花哨的鑄造。

我有一種感覺,你試圖太可愛,錯過了一些基本的OOD原則。考慮如何重構類,以使代碼更簡單。

0

沒有進入的,這是否做的好處,這裏是展示它如何可以進行使用反射一些示例代碼:

Type aaaType = Type.GetType("namespace.AAA"); 
FieldInfo iAField = aaaType.GetField("iA", BindingFlags.Public | 
              BindingFlags.Instance); 
int m = (int)iAField.GetValue(nn); 
+0

這工作 - 謝謝。 – Michael 2013-03-22 19:44:21

0

你爲什麼不嘗試設置抽象屬性在Node類中,並且在AAA和BBB中實現。

public abstract class Node : IDisposable 
{ 
    protected int x; 
    public abstract int i; 
} 
public class AAA : Node 
{ 
    public override int i; 
} 
public class BBB : Node 
{ 
    public override int i; 
} 

而不是使用像這樣的foreach:

foreach (Node nn in MyList)  
{ 
    int m = nn.i;   
} 
0

對我來說,這是你的目標設計的問題,而不是在C#。

你有很多節點,你想一般對待(很好),但你想能夠以獨特的方式從他們那裏獲得專門的數據。在具有(可能)無限量的獨特數據的情況下,這並不是那麼好。

問題是,您想要兩全其美:獨特的封裝數據和對該數據的免費通用訪問。

我想說,你需要採取你的節點設計,並考慮長期和艱難什麼樣的操作/訪問應該可用於節點的通用消費者,並提供抽象基類或小(ish)號碼提供該訪問的接口。否則,你會在代碼中的某個地方尋找許多向下投射的東西,或者使用反射來最好地猜測事物或用於描述和獲取所需值的標準接口。

+0

我對OOP有點新鮮。我們有大約100個不同的節點。 I – Michael 2013-03-22 19:26:44

+0

我創建了一個抽象節點類型,其中包含我們節點的所有常見特徵。然後,我需要從基節點和這些派生節點中派生出100個節點,根據它們的操作擴展它們的特性。如果我有一個汽車課,我會派生福特,豐田等。在福特課上,我會在每輛福特車上添加共同特徵。從福特班級開始,我將派生出野馬班,並增加Mustang特有的特性。如果我創建了一個汽車清單,我想知道野馬的輪胎。這就是我在創建汽車列表時所要做的。也許我錯了。 – Michael 2013-03-22 20:08:53