1

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

我想知道是否可以使用字符串来创建实际的向下转换。也许做不到。也许我错过了一些东西。我想做但不起作用的事情如下。

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 语句来解决这个问题每次添加节点时的语句。如果可能的话,这是我宁愿不做的事情。

提前感谢您的任何回复。

感谢 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

4 回答 4

0

What you are doing seems like a product of a faulty idea somewhere in your design.

Instead of having iA and iB in your classes, why doesn't the base node have a property called iNodeImplementation which you set in the constructor of AAA or BBB? Then you don't have to do all this fancy casting.

I have a feeling your trying to be too cute and missed some basic OOD principles. Consider how you can refactor your classes to make your code simpler.

于 2013-03-22T17:24:36.273 回答
0

在不讨论是否应该这样做的优点的情况下,这里有一些示例代码展示了如何使用反射来完成它:

Type aaaType = Type.GetType("namespace.AAA");
FieldInfo iAField = aaaType.GetField("iA", BindingFlags.Public | 
                                           BindingFlags.Instance);
int m = (int)iAField.GetValue(nn);
于 2013-03-22T17:26:23.163 回答
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;         
}
于 2013-03-22T17:29:33.327 回答
0

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

您有很多节点要进行一般处理(很好),但您希望能够以独特的方式从它们中获取专门的数据。在拥有(可能)无限量的唯一数据的情况下,这并不是很好。

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

我会说您需要进行 Node 设计,并认真思考节点的通用消费者应该可以使用什么样的操作/访问,并在抽象基类或少量(ish)提供的接口中提供它那个访问。

否则,您会在代码中的某处查看大量向下转换,或者使用反射来最好地猜测事物,或者使用标准接口来描述和获取您想要的值。

于 2013-03-22T17:30:02.617 回答