1

I'm creating a list of nodes on the fly through a user interface. In my List I can add any number of objects (AAA, BBB, etc) to the List based on the class structure below by instantiating these objects through reflection.

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

After creating the List I want to access the the extended fields in the derived objects. I know that I have to downcast to access the extended fields but in order to do that presently I have to perform an explicit cast.

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
}

I was wondering if I can use a string to create the actual downcast. Maybe it can't be done. Maybe I'm missing something. What I would like to do which DOESN'T work would be something like the following.

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
}

When I look at the value of nn in the debugger the FullName represents the Class I want to use for the downcast.

I could get around this by using a switch statement based on the string representing the class and hard code in the cast statement but because I have over 100 different nodes and I will be adding more nodes in the future, I would have to modify the switch statement every time a node is added. This is something I would prefer not to do if all possible.

Thanks in advance for any response.

Thanks to Douglas for pointing out that I could use FieldInfo to get the value of iA for example. I just wanted to expand a little more on this topic. If I wanted to take Class AAA and extend it through composition would I also be able to access the fields in those classes through the 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
 }
Michael
  • 41
  • 1
  • 1
  • 7

4 Answers4

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.

Malcolm O'Hare
  • 4,879
  • 3
  • 33
  • 53
0

Without going into the merits of whether this should be done, here's some sample code showing how it can be done using reflection:

Type aaaType = Type.GetType("namespace.AAA");
FieldInfo iAField = aaaType.GetField("iA", BindingFlags.Public | 
                                           BindingFlags.Instance);
int m = (int)iAField.GetValue(nn);
Douglas
  • 53,759
  • 13
  • 140
  • 188
0

Why you don't try to set abstract properties in Node class and than implement in AAA and 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;
}

And than use the foreach like this:

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

To me, this is a problem in your object design, not in C#.

You've got a lot of nodes that you want to treat generically (great) but you want to be able to get specialized data from them in unique ways. This is not so great in the context of having a (possibly) unbounded amount of unique data.

The problem is that you want the best of both worlds: unique encapsulated data and free generic access to that data.

I would say that you need to take your Node design and think long and hard what kind of operations/accessing should be available to generic consumers of the nodes and provide that in an abstract base class or a small(ish) number of interfaces that provide that access.

Otherwise, you're looking at a lot of down-casting somewhere in your code or work with reflection to best guess things or a standard interface for describing and getting the values you want.

plinth
  • 48,267
  • 11
  • 78
  • 120
  • I'm somewhat new to OOP. We have about 100 different nodes. I – Michael Mar 22 '13 at 19:26
  • I created a abstract node type that contains all the common characteristics of our nodes. Then i need to derive 100 nodes from the base node and in those derived nodes, expand their characteristics based on their operation. If I had a car class, I would derive a Ford, Toyota, etc. In the Ford class I would add common features on every Ford. From the Ford class I would derive a Mustang class and add characteristics exclusive to the Mustang. If I created a list of car I would like to know the tires on the Mustang. This is what I'm trying to do as I create my list of Cars. Maybe I'm wrong. – Michael Mar 22 '13 at 20:08