Как добавить 2-кратный производный класс TCollectionItem в TOwnedCollection?
Я хочу реализовать коллекцию или список, используя TOwnedCollection / TCollectionItem. Мне нужен постоянный список (для загрузки и создания из FileStream) классов с полиморфизмом.
Здесь (частично) мой код до сих пор, но мне не удалось создать производный класс TGenerator вместо его родительского TPowerComponent и добавить его в коллекцию.
//-------------------------------------------------------------------------------------
class TPCCollection : public TOwnedCollection
{
typedef TOwnedCollection inherited;
private:
TPowerComponent* __fastcall GetPowerComponent(int Index);
void __fastcall SetPowerComponent(int Index, TPowerComponent *Value);
public:
__fastcall TPCCollection(TPersistent *Owner);
HIDESBASE TPowerComponent* __fastcall Add(void);
HIDESBASE TPowerComponent* __fastcall Insert(int Index);
__property TPowerComponent* PCCollection[int Index] = {read=GetPowerComponent, write=SetPowerComponent};
};
//-------------------------------------------------------------------------------------
class TPowerComponent : public TCollectionItem
{
typedef TCollectionItem inherited;
public :
int X, Y, Rotation;
PowSymbType HisType;
__fastcall TPowerComponent(TCollection *Collection, PowSymbType AType );
void __fastcall Assign(TPersistent *Source);
virtual void __fastcall Paint(TCanvas * Canvas);
};
//-------------------------------------------------------------------------------------
class TGenerator : public TPowerComponent
{
typedef TPowerComponent inherited;
public :
double PG, Qgmin, Qgmax, Vsch;
__fastcall TGenerator(TCollection *Collection, PowSymbType AType );
void __fastcall Assign(TPersistent *Source);
virtual void __fastcall Paint(TCanvas * Canvas);
};
//-------------------------------------------------------------------------------------
// implementation
//-------------------------------------------------------------------------------------
// TPCCOllection
//-------------------------------------------------------------------------------------
__fastcall TPCCollection::TPCCollection(TPersistent *Owner)
: TOwnedCollection(Owner, __classid(TPowerComponent))
{
}
//-------------------------------------------------------------------------------------
TPowerComponent* __fastcall TPCCollection::Add()
{
return static_cast<TPowerComponent>(inherited::Add());
}
//-------------------------------------------------------------------------------------
TPowerComponent* __fastcall TPCCollection::Insert(int Index)
{
return static_cast<TPowerComponent>(inherited::Insert(Index));
}
//-------------------------------------------------------------------------------------
TPowerComponent* __fastcall TPCCollection::GetPowerComponent(int Index)
{
return static_cast<TPowerComponent>(inherited::GetItem(Index));
}
//-------------------------------------------------------------------------------------
void __fastcall TPCCollection::SetPowerComponent(int Index, TPowerComponent *Value)
{
inherited::SetItem(Index, Value);
}
//-------------------------------------------------------------------------------------
// TPowerComponent
//-------------------------------------------------------------------------------------
__fastcall TPowerComponent::TPowerComponent(TCollection *Collection, PowSymbType AType )
: TCollectionItem(Collection)
{
HisType=AType;
Rotation=0;
}
//-------------------------------------------------------------------------------------
void __fastcall TPowerComponent::Assign(TPersistent *Source)
{
TPowerComponent *Src = dynamic_cast<TPowerComponent>(Source);
if( Src )
{
// copy members from Src...
}
else inherited::Assign(Source);
}
//-------------------------------------------------------------------------------------
// se dessine
void __fastcall TPowerComponent::Paint(TCanvas * Canvas)
{
...
}
//-------------------------------------------------------------------------------------
// TGenerator
//-------------------------------------------------------------------------------------
__fastcall TGenerator::TGenerator(TCollection *Collection, PowSymbType AType )
:TPowerComponent( Collection, AType )
{
PG=0; Qgmin=0; Qgmax=0; Vsch=1.0; Con=-1;
}
//-------------------------------------------------------------------------------------
void __fastcall TGenerator::Assign(TPersistent *Source)
{
TGenerator *Src = dynamic_cast<TGenerator>(Source);
if( Src )
{
// copy members from Src...
}
else inherited::Assign(Source);
}
//-------------------------------------------------------------------------------------
// Usage
TPCCollection * NetWork = new TPCCollection(this);
// Usage to Access all the collection
for( int i=0; i< NetWork->Count; i++)
{
((TPowerComponent*)(NetWork->Items[i]))->Paint(Canvas);
}
Чтобы добавить TGenerator, а не TPowerComponent, я использую:
TGenerator * Gen=new TGenerator( NetWork, Generator);
Создание дочернего элемента TCollectionItem автоматически добавляется в TCollection.
Проблема в том, что мы не можем отделить процесс создания элемента от добавления его в коллекцию.
Когда мне нужен другой список, который может содержать некоторые элементы из первого списка коллекции, например, SelectedComponents может иметь один или несколько элементов коллекции NetWork, без их повторного создания.
Это может быть сделано с
std::list<TPowerComponent*> SelectedComponents;
но я не могу написать / прочитать их, используя FileStream / постоянный список. Мне нужно поместить их в TCollection, но не воссоздавая их.
Как?
1 ответ
Собственная потоковая передача RTF для RTL TCollection
объекты только частично поддерживают полиморфные TCollectionItem
классы.
Вы можете добавить полиморфный TCollectionItem
возражает против TCollection
в коде (во время выполнения, а также во время разработки с помощью пользовательского редактора), если они все происходят из общего базового класса, который передается в TCollection
конструктор. И такую коллекцию можно даже сохранить как есть в DFM.
Однако при загрузке DFM при потоковой передаче все элементы коллекции, считанные из DFM, будут использовать все TCollectionItem
тип класса вы передаете TCollection
конструктор. Таким образом, полиморфные классы не могут быть загружены изначально.
Единственный способ переопределить это поведение - отключить потоковую передачу для коллекции (TCollection
свойство быть не published
или, по крайней мере, пометить его как stored=false
), а затем выполните потоковую передачу элементов коллекции вручную.
Есть ваш основной компонент (или что-то еще TPersistent
класс владеет коллекцией) переопределить виртуальный DefineProperties()
метод для вызова TFiler.DefineProperty()
зарегистрировать пользовательские методы чтения / записи для потоковой передачи элементов коллекции. Чтобы поддерживать полиморфные классы, вам нужно написать каждый элемент ClassName
в DFM перед записью значений его свойств, затем прочитайте имя обратно, чтобы вы знали, какой класс создать, прежде чем читать значения свойств.