1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
//---------------------------------------------------------------------------
/*override*/void __fastcall TShaiORPersistent::Assign(TPersistent* Source)
{
this->PrimaryID = -1;
if (Source->InheritsFrom(__classid(TShaiORPersistent)))
{
this->DataSource = ((TShaiORPersistent*)Source)->DataSource;
if ( ! this->DataSource)
SetPublishedPropertiesFromPersistent(Source);
}
else if (Source->InheritsFrom(__classid(TDataSet)))
{
this->DataSource = NULL;
SetPublishedPropertiesFromDataSet((TDataSet*)Source);
}
else
inherited::Assign(Source);
}
//---------------------------------------------------------------------------
/**
* SetPublishedPropertiesFromDataSet fill object with DataSet
* @return number of affected properties (-1 on null or empty DataSet)
*/
int TShaiORPersistent::SetPublishedPropertiesFromDataSet(TDataSet* ADataSet)
{
int Result = -1;
if (ADataSet && ! ADataSet->IsEmpty())
{
Result = 0;
for (int i = 0; i < ADataSet->FieldCount; i++)
{
TField *Field = ADataSet->Fields->Fields[i];
AnsiString PropertyName = PropertyNameByFieldName(Field->FieldName);
if ( ! PropertyName.IsEmpty())
{
// Certaines propriétés publiées peuvent être en Lecture Seule, le chargement doit se faire manuellement !
if (Typinfo::GetPropInfo(this, PropertyName)->SetProc)
{
Variant CopyValue = Field->Value;
// Une Gestion minimale du Null, le type Variant permettra de gérer pleinement cet état au besoin !
if (Field->IsNull)
{
switch (TShaiRTTIWrapper::GetPersistentType(this->ClassType(), PropertyName))
{
// Variant reste Intact car gère naturellement le Null
case tkInteger :
case tkFloat:
case tkInt64 :
CopyValue = 0;
break;
case tkString :
case tkLString :
case tkWString :
CopyValue = "";
break;
}
}
// Remarques :
// - Ne pas utiliser de passage de paramètre par référence dans les Setter, SetPropValue ou SetStrProp ne les gère pas !
// - L'ordre des constructeurs et de l'instanciation statique des membres d'un objet C++ est par itération successive,
// la conséquence est qu'il ne faut pas utiliser String statique mais bien String* dynamique pour contourner ce mécanisme !
// C'est d'ailleurs, ce phénomène qui empêche de bénéficier pleinement des méthodes virtuelles dans un constructeur (cela dépend si TObject ou pas !)
// Intervention sur les Forums en tant que ShaiLeTroll :
// - Virtual - www.developpez.net/forums/d1059827/c-cpp/outils-c-cpp/cppbuilder/methodes-virtuelles-appeles-constructeur/
Typinfo::SetPropValue(this, PropertyName, CopyValue);
Result++;
}
}
}
}
return Result;
}
//---------------------------------------------------------------------------
/**
* SetPublishedPropertiesFromPersistent fill object with another object
* @return number of affected properties (-1 on null object)
*/
int TShaiORPersistent::SetPublishedPropertiesFromPersistent(TPersistent* APersistent)
{
int Result = -1;
if (APersistent)
{
Result = 0;
TStringList *PropList = new TStringList();
try
{
if (TShaiRTTIWrapper::GetPersistentProperties(APersistent->ClassType(), PropList))
{
for (int i = 0; i < PropList->Count; i++)
{
AnsiString PropertyName = PropList->Strings[i];
// Certaines propriétés publiées peuvent être en Lecture Seule, le chargement doit se faire manuellement !
if (Typinfo::IsPublishedProp(this, PropertyName) && GetPropInfo(this, PropertyName)->SetProc)
{
Typinfo::SetPropValue(this, PropertyName, GetPropValue(APersistent, PropertyName, false));
Result++;
}
}
}
}
__finally
{
delete PropList;
}
}
return Result;
} |
Partager