2013-03-22 71 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