访问派生类中的字段

时间:2013-03-22 17:12:16

标签: c#

我正在通过用户界面动态创建节点列表。在我的列表中,我可以通过反射实例化这些对象,根据下面的类结构向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;
}

创建List后,我想访问派生对象中的扩展字段。我知道我必须向下转换才能访问扩展字段,但为了做到这一点,我必须执行显式转换。

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
}

我想知道我是否可以使用字符串来创建实际的向下转换。也许它无法完成。也许我错过了什么。我想做的哪些不起作用就像下面这样。

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表示我想要用于向下转换的类。

我可以通过使用基于表示类和转换语句中的硬代码的字符串的switch语句来解决这个问题,但因为我有超过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
 }

4 个答案:

答案 0 :(得分:0)

你正在做的事情似乎是你设计中某个错误想法的产物。

为什么基类节点没有在AAA或BBB的构造函数中设置的名为iNodeImplementation的属性,而不是在类中使用iA和iB?然后你不必做所有这些花哨的演员。

我有一种感觉,你试图太可爱,错过了一些基本的OOD原则。考虑如何重构类以使代码更简单。

答案 1 :(得分:0)

如果没有考虑是否应该完成的优点,这里有一些示例代码,展示了可以使用反射完成的方式:

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

答案 2 :(得分: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;         
}

答案 3 :(得分:0)

对我来说,这是对象设计中的一个问题,而不是C#。

你有很多想要一般性处理的节点(很棒),但是你希望能够以独特的方式从它们那里获得专门的数据。在具有(可能)无限量的唯一数据的情况下,这并不是那么好。

问题是你想要两全其美:独特的封装数据和对这些数据的免费通用访问。

我想说你需要采用你的Node设计,并认真考虑节点的一般消费者应该可以使用哪种操作/访问,并在抽象基类或小(ish)数量的提供该访问的接口。

否则,你会在你的代码中的某个地方看到很多内容,或者使用反射来最好地猜测事物,或使用标准接口来描述和获取你想要的值。