2013-03-22 2 views
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 
} 

Мне было интересно, могу ли я использовать строку для создания фактического 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 
} 

Когда я смотрю на значение пп в отладчике ПолноеИмя представляет класс я хочу использовать для смиренных.

Я мог бы обойти это, используя оператор switch на основе строки, представляющей класс и жесткий код в операторе cast, но поскольку у меня есть более 100 различных узлов, и я буду добавлять больше узлов в будущем, я бы изменять инструкцию switch каждый раз, когда узел добавляется. Это то, что я бы предпочел не делать, если все возможно.

Заранее благодарим за любой ответ.

Благодаря Дугласу, указав, что я могу использовать 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

+0

Это похоже на идеальное использование для дженериков, но для того, чтобы сказать, что больше потребуется увидеть немного больше ваших использование приложения. –

+0

Вам не понадобится инструкция switch, чтобы узнать, ищете ли вы свойство iA типа AAA или iB по типу BBB? –

ответ

0

То, что вы делаете, похоже на продукт ошибочной идеи где-то в вашем дизайне.

Вместо того, чтобы иметь iA и iB в ваших классах, почему базовый узел не имеет свойства, называемого iNodeImplementation, которое вы задали в конструкторе AAA или BBB? Тогда вам не нужно делать все это причудливое кастинг.

У меня такое чувство, что вы пытаетесь быть слишком симпатичным и пропустили некоторые основные принципы 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

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 (Node nn in MyList)  
{ 
    int m = nn.i;   
} 
0

Для меня, это проблема в вашем дизайне объекта, а не в C#.

У вас есть много узлов, которые вы хотите обрабатывать в целом (отлично), но вы хотите получить уникальные данные из них.Это не так велико в контексте наличия (возможно) неограниченного количества уникальных данных.

Проблема в том, что вы хотите получить лучшее из обоих миров: уникальные инкапсулированные данные и бесплатный общий доступ к этим данным.

Я бы сказал, что вам нужно принять дизайн узла и долго и долго думать, какие операции/доступ к ним должны быть доступны универсальным потребителям узлов и обеспечить это в абстрактном базовом классе или небольшом (ish) числе интерфейсов, обеспечивающих этот доступ.

В противном случае вы смотрите на то, чтобы сбрасывать где-то в вашем коде или работать с отражением, чтобы лучше всего угадывать вещи или стандартный интерфейс для описания и получения желаемых значений.

+0

Я немного новичок в ООП. У нас около 100 различных узлов. I – Michael

+0

Я создал абстрактный тип узла, который содержит все общие характеристики наших узлов. Затем мне нужно вывести 100 узлов из базового узла и в эти производные узлы, расширить их характеристики на основе их работы. Если бы у меня был класс автомобилей, я бы получил Ford, Toyota и т. Д. В классе Ford я бы добавил общие функции на каждом Ford. Из класса Ford я бы получил класс Mustang и добавил характеристики, исключительные для Mustang. Если бы я создал список автомобилей, я бы хотел узнать шины на Mustang. Это то, что я пытаюсь сделать, когда создаю свой список автомобилей. Возможно, я ошибаюсь. – Michael

Смежные вопросы