Tipy pro Windows Phone 7 aplikace IV - intermezzo I - zjednodušená registrace serializovatelných tříd nesoucích tranzientní stav v KnownTypesDictionary
Dnešní článek je jen “intermezzem”, protože doplňuje předchozí článek o slíbenou informaci, jak můžeme automaticky registrovat serializovatelné třídy, jejichž instance nesou tranzientní stav, který je uložen v KnownTypesDictionary. Přechozí článek končil ukázkou, jak můžeme vrátit staticky definovaný seznam typů, dnes se poohlédneme po trochu dynamičtějším řešení. I když postup není omezen jen na WP7 aplikace, ale můžete ho použít v kterékoli aplikaci, která využívá (WCF) DataContractSerializer, my se zaměříme v článku opět hlavně na řešení WP7 specialitek.
Přečetli jste si první odstavec a nevíte, co je tranzientní stav? Hledáte marně v MSDN typ KnownTypesDictionary? Nedivte se, milostný akt sice můžete rozjet bez předehry, ale abyste rozuměli tomuto intermezzu, pečlivě a pomalu si přečtěte jako předehru k intermezzu tipy pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu) ve "view modelech”, i díl třetí, kde se bavíme o KnownTypesDctionary.
Předehru máte za sebou, takže víte, že KnownTypesDictionary je specializovaný objekt Dictionary, ve kterém je klíčem řetězec a hodnotou libovolný objekt a že v objektech KnownTypesDictionary ukládáme tranzientní stav view modelů při každém “tombstoningu”. I když KnownTypesDictionary může jako hodnotu nést libovolný objekt, my musíme instruovat DataContractSerializer, které objekty a hlavně z kterých odvozených tříd má v objektu Dictionary očekávat.
Když do KnownTypesDictionary ukládáme v jedné aplikaci instance z tříd OrderVO a InvoiceVO a v jiné aplikaci instance TwitterPost a ObservableCollection<TwitterPost >, musíme vždy znovu zmíněné třídy registrovat pomocí atributu KnownType.
Pro připomenutí následuje výpis kódu, kterým jsme končili a který registruje serializovatelné třídy v aplikaci “natvrdo” pomocí statické metody GetKnownTypes, jejíž název je předán do konstruktoru atributu KnownType.
Napevno zadrátované typy v KnownTypesDctionary nám nemusí vadit v jedné aplikaci, ale když chceme používat KnownTypesDctionary v mnoha různých aplikacích, musím řešení upravit.
Místo abychom třídy v metodě GetKnownTypes registrovali přímo, delegujeme odpovědnost za vrácení serializovatelných typů na specializovaného poskytovatele.
BTW: To víte, že první a okouzlující zákon vztahu mezi třídami zní: “Když je třída vyčerpána množstvím odpovědností, vždy si může přičarovat otroka, který špinavou práci udělá za ni”?. Občas se tomuto zákonu také říká SRP – princip jedné odpovědnosti třídy”.
Poskytovatel je objekt podporující rozhraní IKnownTypeProvider s jednou samopopisnou metodou.
Refaktorizujeme třídu KnownTypesDictionary, aby při vracení serializovatelných typů využívala objekt IKnownTypeProvider.
Do nové statické vlastnosti KnownTypeProvider je ve statickém konstruktoru přiřazen DefaultKnownTypesProvider, o kterém budeme mluvit za chvíli, ale do vlastnosti KnownTypeProvider můžete klidně vložit pro účely vaší aplikace lépe přizpůsobený IKnownTypeProvider.
Metoda GetKnownTypes vrátí všechny staticky registrované typy v poli KNOWN_TYPES společně s typy, které dodá IKnownTypeProvider. Typy jsou získány jen při prvním volání metody GetKnownTypes a jsou cachovány v proměnné _cachedKnownTypes, abychom opakovaným získáním typů z IKnownTypeProvider zbytečně neplýtvali výkonem WP7 telefonů ani trpělivostí uživatele. Předpokladem tohoto přístupu samozřejmě je, že v aplikaci je fixní množina serializovatelných typů, která se za běhu aplikace již nemění. Jestli vám to nevyhovuje, odstraníte cache z KnownTypesDictionary za 10 sekund.
Jaké odpovědnosti bude mít DefaultKnownTypesProvider?
- DefaultKnownTypesProvider nám vrátí všechny deskriptory třídy (Type) označené atributem [DataContract] v hlavní assembly aplikace.
- DefaultKnownTypesProvider nám vrátí všechny deskriptory třídy (Type) označené atributem [DataContract] v dalších assembly, ze kterých je složena aplikace.
- DefaultKnownTypesProvider nalezne další a pro aktuální aplikaci specifické objekty podporující rozhraní IKnownTypeProvider a vrátí seznam všech typů z těchto providerů.
- Pro všechny nalezené typy T zaregistruje i kolekci Observable<T>. To znamená, že pro třídu OrderVO označenou atributem DataContract je automaticky vrácen z poskytovatele nejen její Type (typof(OrderVO), ale i deskriptor kolekce typeof(ObservableCollection<OrderVO>).
Kód třídy DefaultKnownTypesProvider:
V metodě GetKnownTypes vyzvedneme všechny typy z “hlavní” (vstupní) assembly. Hlavní assembly získáme v metodě getExecutingAssembly přes vlastnosti třídy Deployment.
Typy z hlavní assembly sloučíme s typy v dalších assembly voláním metody getRefencedAssembliesTypes(). Ve WP7 jsem bohužel nenašel způsob, jak seznam dalších assembly získat, a proto další assembly poskytují objekty IAssemblyTypesProvider nalezené v hlavní assembly.
Chcete-li tedy automaticky vyhledat typy označené atributem DataContract v další assembly, vložte do hlavní assembly třídu podporující rozhraní IAssemblyTypesProvider.
Do proměnné collectionTypes v metodě GetKnownTypes vygenerujeme pro všechny nalezené typy jejich kolekce. Možná trochu složitě vypadající kód jen zabraňuje tomu, abyste nalezené deskriptory tříd typu ObservableCollection<T> v proměnné types balili znovu do kolekce ObservableCollection. Jinými slovy, když v proměnné types bude kolekce ObservableCollection<OrderVO>, do proměnné collectionTypes nebude generována kolekce ObservableCollection<ObservableCollection<OrderVO>>.
Na konci vracíme nalezené typy sloučené s vygenerovanými typy kolekcí ObservableCollection<T> a dalšími a pro aplikaci specifickými typy z ostatnich poskytovatelů . Za poskytovatele považujeme další objekty IKnownTypeProvider nalezené v hlavní assembly.
A tím máme hotovo.
Připomínám, že DefaultKnownTypesProvider můžete využít nejen ve WP7 aplikacích, ale ve všech aplikacích v .Net Frameworku, kde je používán DataContractSerializer a vy chcete automaticky registrovat odvozené serializovatelné typy.
Příště již začneme stavět aplikaci založenou na našem "mini frameworku”, abyste viděli, k čemu tyto počáteční díly seriálu včetně intermezza, které právě čtete, vůbec byly.
Předcházející články:
Tipy pro Windows Phone 7 aplikace I
Tipy pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu) ve "view modelech”
Tipy pro Windows Phone 7 aplikace III–propojení view modelu s view (stránkou)
Monday, January 10, 2011 1:37:12 PM (Central Europe Standard Time, UTC+01:00)
.NET Framework | C# | Návrhové vzory | Silverlight | WP7