Optymalizacja stanu trwałego i inicjalizacji
Domyślnie trwałość i inicjowanie w kontrolce są obsługiwane przez funkcję składową DoPropExchange
. W typowej kontrolce ta funkcja zawiera wywołania kilku funkcji PX_ (PX_Color
, PX_Font
itd.), po jednym dla każdej właściwości.
Takie podejście ma zaletę, że pojedyncza DoPropExchange
implementacja może służyć do inicjowania, trwałości w formacie binarnym i trwałości w tak zwanym formacie "property-bag" używanym przez niektóre kontenery. Ta jedna funkcja udostępnia wszystkie informacje o właściwościach i ich wartościach domyślnych w jednym wygodnym miejscu.
Jednak ta ogólnalność wiąże się z kosztem wydajności. Funkcje PX_ zapewniają elastyczność dzięki wielowarstwowym implementacjom, które są z natury mniej wydajne niż bardziej bezpośrednie, ale mniej elastyczne. Ponadto jeśli kontrolka przekazuje wartość domyślną do funkcji PX_ , ta wartość domyślna musi być podana za każdym razem, nawet w sytuacjach, gdy wartość domyślna może nie być używana. Jeśli generowanie wartości domyślnej jest zadaniem nietrywialnym (na przykład gdy wartość jest uzyskiwana z właściwości otoczenia), dodatkowa niepotrzebna praca jest wykonywana w przypadkach, gdy wartość domyślna nie jest używana.
Wydajność trwałości binarnej kontrolki można poprawić, przesłaniając funkcję kontrolki Serialize
. Domyślna implementacja tej funkcji składowej wykonuje wywołanie DoPropExchange
funkcji. Przesłaniając ją, można zapewnić bardziej bezpośrednią implementację dla trwałości binarnej. Rozważmy na przykład tę DoPropExchange
funkcję:
void CMyAxOptCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
PX_Bool(pPX, _T("BoolProp"), m_BoolProp, TRUE);
PX_Short(pPX, _T("ShortProp"), m_ShortProp, 0);
PX_Color(pPX, _T("ColorProp"), m_ColorProp, RGB(0xFF, 0x00, 0x00));
PX_String(pPX, _T("StringProp"), m_StringProp, _T(""));
}
Aby zwiększyć wydajność trwałości binarnej tej kontrolki, można zastąpić Serialize
funkcję w następujący sposób:
void CMyAxOptCtrl::Serialize(CArchive& ar)
{
SerializeVersion(ar, MAKELONG(_wVerMinor, _wVerMajor));
SerializeExtent(ar);
SerializeStockProps(ar);
if (ar.IsLoading())
{
ar >> m_BoolProp;
ar >> m_ShortProp;
ar >> m_ColorProp;
ar >> m_StringProp;
}
else
{
ar << m_BoolProp;
ar << m_ShortProp;
ar << m_ColorProp;
ar << m_StringProp;
}
}
Zmienna lokalna dwVersion
może służyć do wykrywania wersji stanu trwałego, który jest ładowany lub zapisywany. Tej zmiennej można użyć zamiast wywoływać CPropExchange ::GetVersion.
Aby zaoszczędzić trochę miejsca w formacie trwałym dla właściwości BOOL (i zachować jej zgodność z formatem utworzonym przez PX_Bool
program ), można przechowywać właściwość jako BYTE w następujący sposób:
if (ar.IsLoading())
{
BYTE bTmp;
ar >> bTmp;
m_BoolProp = (BOOL)bTmp;
// other properties...
}
else
{
ar << (BYTE)m_BoolProp;
// other properties...
}
Należy pamiętać, że w przypadku obciążenia jest używana zmienna tymczasowa, a następnie jej wartość jest przypisywana, a nie rzutowanie m_boolProp do odwołania BYTE . Technika rzutowania spowoduje zmodyfikowanie tylko jednego bajtu m_boolProp , pozostawiając pozostałe bajty niezainicjowane.
Dla tej samej kontrolki można zoptymalizować inicjowanie kontrolki przez zastąpienie COleControl::OnResetState w następujący sposób:
void CMyAxOptCtrl::OnResetState()
{
ResetVersion(MAKELONG(_wVerMinor, _wVerMajor));
ResetStockProps();
m_BoolProp = TRUE;
m_ShortProp = 0;
m_ColorProp = RGB(0xFF, 0x00, 0x00);
m_StringProp.Empty();
}
Mimo że Serialize
i OnResetState
zostały zastąpione, funkcja powinna być zachowana bez zmian, DoPropExchange
ponieważ jest nadal używana do trwałości w formacie właściwości-bag. Ważne jest, aby zachować wszystkie trzy z tych funkcji, aby upewnić się, że kontrolka zarządza jej właściwościami spójnie, niezależnie od tego, który mechanizm trwałości używa kontenera.