<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>René Stein - Návrhové vzory</title>
    <link>http://blog.renestein.net/</link>
    <description>Názory vzešlé z mesaliance humanitní skepse a technologického optimismu</description>
    <image>
      <url>http://blog.renestein.net/themes/discreetBlogBlue/SpotImages/sfinga_rss.jpg</url>
      <title>René Stein - Návrhové vzory</title>
      <link>http://blog.renestein.net/</link>
    </image>
    <language>cs-CZ</language>
    <copyright>René Stein</copyright>
    <lastBuildDate>Tue, 19 Aug 2014 10:08:00 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.7174.0</generator>
    <managingEditor>rene@renestein.net</managingEditor>
    <webMaster>rene@renestein.net</webMaster>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=ffc2e5e3-87f1-4f53-9a2a-331171cc0ec4</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,ffc2e5e3-87f1-4f53-9a2a-331171cc0ec4.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,ffc2e5e3-87f1-4f53-9a2a-331171cc0ec4.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=ffc2e5e3-87f1-4f53-9a2a-331171cc0ec4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Rád bych vás pozval na svou přednášku, kterou pořádá WUG.
</p>
        <p>
Název přednášky: TPL - konkurenční, paralelní a asynchronní kód pro náročné.
</p>
        <h6>
          <font size="3">Datum konání: 2.10.2014 od 17:30 do 21:00</font>
        </h6>
        <p>
Místo konání: pobočka: <a href="http://wug.cz/praha/prednaskove-prostory/18-BB-centrum-budova-Alfa">BB
centrum, budova Alfa (Aquarius), Vyskočilova 1461/2a, Praha 4</a></p>
        <p>
Registrace na přednášku: <a href="http://wug.cz/praha/akce/597-TPL-konkurencni-paralelni-a-asynchronni-kod-pro-narocne">http://wug.cz/praha/akce/597-TPL-konkurencni-paralelni-a-asynchronni-kod-pro-narocne</a></p>
        <p>
Anotace přednášky:
</p>
        <p>
Znáte alespoň trochu Task Parallel Library a přednášek slibujících další nenáročný
„úvod do TPL“ jste už viděli dost? Myslíte si, že klíčová slova async/await v C# jsou
magií kompilátoru, jejíž kouzlo pro vás už navěky pominulo po zhlédnutí triviálních
a donekonečna opisovaných příkladů, jak zavolat asynchronně pár nudných webových služeb?
</p>
        <p>
Na přednášce probereme, jak rozšířit knihovnu TPL o další užitečné konstrukce i jak
odstranit některá omezení v současné verzi TPL. Podíváme se na různé způsoby psaní
konkurenčního, paralelního a asynchronního kódu. U konkurenčního kódu se zaměříme
(nejen) na aktory a porovnáme různé způsoby, jak můžeme aktory psát.
</p>
        <p>
Nezapomeňte s sebou vzít i kolegy, kteří hlásají, že každou nebezpečnou hlavu konkurenčního
kódu setne jeden pořádný „lock“, a to nejlépe rekurzivní, aby vás deadlock nebo livelock
ve firmě zabavil i o dlouhých zimních večerech.
</p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=ffc2e5e3-87f1-4f53-9a2a-331171cc0ec4" />
      </body>
      <title>Veřejn&amp;aacute; předn&amp;aacute;&amp;scaron;ka pro WUG - TPL &amp;ndash; konkurenčn&amp;iacute;, paraleln&amp;iacute; a asynchronn&amp;iacute; k&amp;oacute;d pro n&amp;aacute;ročn&amp;eacute;.</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,ffc2e5e3-87f1-4f53-9a2a-331171cc0ec4.aspx</guid>
      <link>http://blog.renestein.net/Ve%c5%99ejnaacute+P%c5%99ednaacutescaronka+Pro+WUG+TPL+Ndash+Konkuren%c4%8dniacute+Paralelniacute+A+Asynchronniacute+Koacuted+Pro+Naacutero%c4%8dneacute.aspx</link>
      <pubDate>Tue, 19 Aug 2014 10:08:00 GMT</pubDate>
      <description>&lt;p&gt;
Rád bych vás pozval na svou přednášku, kterou pořádá WUG.&lt;p&gt;
Název přednášky: TPL - konkurenční, paralelní a asynchronní kód pro náročné.&lt;h6&gt;&lt;font size="3"&gt;Datum
konání: 2.10.2014 od 17:30 do 21:00&lt;/font&gt;
&lt;/h6&gt;
&lt;p&gt;
Místo konání: pobočka: &lt;a href="http://wug.cz/praha/prednaskove-prostory/18-BB-centrum-budova-Alfa"&gt;BB
centrum, budova Alfa (Aquarius), Vyskočilova 1461/2a, Praha 4&lt;/a&gt;
&lt;p&gt;
Registrace na přednášku: &lt;a href="http://wug.cz/praha/akce/597-TPL-konkurencni-paralelni-a-asynchronni-kod-pro-narocne"&gt;http://wug.cz/praha/akce/597-TPL-konkurencni-paralelni-a-asynchronni-kod-pro-narocne&lt;/a&gt;
&lt;p&gt;
Anotace přednášky:&lt;p&gt;
Znáte alespoň trochu Task Parallel Library a přednášek slibujících další nenáročný
„úvod do TPL“ jste už viděli dost? Myslíte si, že klíčová slova async/await v C# jsou
magií kompilátoru, jejíž kouzlo pro vás už navěky pominulo po zhlédnutí triviálních
a donekonečna opisovaných příkladů, jak zavolat asynchronně pár nudných webových služeb?&lt;p&gt;
Na přednášce probereme, jak rozšířit knihovnu TPL o další užitečné konstrukce i jak
odstranit některá omezení v současné verzi TPL. Podíváme se na různé způsoby psaní
konkurenčního, paralelního a asynchronního kódu. U konkurenčního kódu se zaměříme
(nejen) na aktory a porovnáme různé způsoby, jak můžeme aktory psát.&lt;p&gt;
Nezapomeňte s sebou vzít i kolegy, kteří hlásají, že každou nebezpečnou hlavu konkurenčního
kódu setne jeden pořádný „lock“, a to nejlépe rekurzivní, aby vás deadlock nebo livelock
ve firmě zabavil i o dlouhých zimních večerech.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=ffc2e5e3-87f1-4f53-9a2a-331171cc0ec4" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,ffc2e5e3-87f1-4f53-9a2a-331171cc0ec4.aspx</comments>
      <category>.NET Framework</category>
      <category>C#</category>
      <category>Návrhové vzory</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=4248081e-7a49-49ae-bd23-7a241892a7e0</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,4248081e-7a49-49ae-bd23-7a241892a7e0.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,4248081e-7a49-49ae-bd23-7a241892a7e0.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=4248081e-7a49-49ae-bd23-7a241892a7e0</wfw:commentRss>
      <title>Task Parallel Library a RStein. Async 5 z n &amp;ndash; Hrajeme si s ThreadPoolSchedulerem</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,4248081e-7a49-49ae-bd23-7a241892a7e0.aspx</guid>
      <link>http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+5+Z+N+Ndash+Hrajeme+Si+S+ThreadPoolSchedulerem.aspx</link>
      <pubDate>Wed, 25 Jun 2014 03:30:00 GMT</pubDate>
      <description>&lt;p&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
Po napsání &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduleru
v předchozím díle&lt;/a&gt; následuje další slíbený oddychový díl, ve kterém si máme s &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolSchedulerem&lt;/a&gt; pohrát.
Název je možná trochu zavádějící, protože nás žádné rozkošné hrátky nečekají.&lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduler&lt;/a&gt;&amp;nbsp;
zcela pragmaticky otestujeme, abychom si potvrdili, že jde o plně funkční threadpool&amp;nbsp;
a že se takový threadpool dá použít všude, ke je očekáván TPL scheduler.
&lt;/p&gt;
&lt;p&gt;
Jako vždy připomenu, že knihovna &lt;a href="https://bitbucket.org/renestein/rstein.async/src/723f7a7e9ca83a228e29af3565ff82e560a9ed5d?at=master"&gt;RStein.Async&lt;/a&gt;,
ve které naleznete i &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduler&lt;/a&gt;,
je dostupná&amp;nbsp; na &lt;a href="https://bitbucket.org/renestein/rstein.async/src"&gt;Bitbucketu&lt;/a&gt;. 
&lt;br&gt;
&lt;em&gt;git clone &lt;/em&gt;&lt;a href="mailto:git@bitbucket.org:renestein/rstein.async.git"&gt;&lt;em&gt;git@bitbucket.org:renestein/rstein.async.git&lt;/em&gt;&lt;/a&gt; 
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;strong&gt;Seriál&amp;nbsp; Task Parallel Library a RStein.Async&amp;nbsp; (předběžná osnova)&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;Task
Parallel Library a RStein. Async 1 z n –&amp;nbsp; Popis základních tříd a obcházení omezení
v TPL.&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+2+Ndash+Boost+ASIO+V+Net+A+IoServiceScheduler.aspx"&gt;Task
Parallel Library a RStein. Async 2 z n –&amp;nbsp; (boost) ASIO v .Net a IoServiceScheduler.&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+3+Z+N+Ndash+Ukaacutezky+Pou%C5%BEitiacute+IoServiceScheduleru+Coroutines.aspx"&gt;Task
Parallel Library a RStein. Async 3 z n – Ukázky použití IoServiceScheduleru. Coroutines.&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+4+Z+N+Ndash+ThreadPoolScheduler+Zalo%c5%beenyacute+Na+IoServiceScheduleru.aspx"&gt;Task
Parallel Library a RStein. Async 4 z n&amp;nbsp; – ThreadPoolScheduler založený na IoServiceScheduleru.&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Task Parallel Library a RStein. Async 5 z n – Hrajeme si s ThreadPoolSchedulerem.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Task Parallel Library a RStein. Async 6 z n – Vytvoření StrandScheduleru.
&lt;/p&gt;
&lt;p&gt;
Task Parallel Library a RStein. Async 7 z n – Náhrada za některé synchronizační promitivy
– ConcurrentStrandSchedulerPair.
&lt;/p&gt;
&lt;p&gt;
Task Parallel Library a RStein. Async 8 z n – Jednoduchý “threadless” actor model
s využitím StrandScheduleru.
&lt;/p&gt;
&lt;p&gt;
Task Parallel Library a RStein. Async 9 z n – Píšeme aktory I.
&lt;/p&gt;
&lt;p&gt;
Task Parallel Library a RStein. Async 10 z n – Píšeme aktory II.
&lt;/p&gt;
&lt;p&gt;
Task Parallel Library a RStein. Async 11 z n – Píšeme nový synchronizační kontext&amp;nbsp;
- IoServiceSynchronizationContext.
&lt;/p&gt;
&lt;p&gt;
Task Parallel Library a RStein. Async 12 z n – Použití IoServiceSynchronizationContextu
v konzolové aplikaci a Windows službě.
&lt;/p&gt;
&lt;p&gt;
(bude upřesněno)
&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;em&gt;Poznámka: V celé sérii článků budu používat slovo Task pro třídu, task pro název
proměnné / argumentu metody a ”anglicismy” tásk/tásky místo “úloha/úlohy“ nebo jiného
českého patvaru při zmínce o /úlohách-táscích/ v dalším textu. Předpokládám, že pro
většinu vývojářů je takový text srozumitelnější.&lt;/em&gt; 
&lt;p&gt;
Vytvoříme si &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduler&lt;/a&gt; pro
testy.
&lt;/p&gt;
&lt;script src="https://gist.github.com/renestein/864ad719fbd30d38767b.js"&gt;&lt;/script&gt;
&lt;p&gt;
V metodě InitializeTest třídy IoServiceThreadPoolSchedulerTests vytvoříme &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+2+Ndash+Boost+ASIO+V+Net+A+IoServiceScheduler.aspx"&gt;IoServiceScheduler&lt;/a&gt;,
předáme ho do konstruktoru &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduleru&lt;/a&gt; a &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduler&lt;/a&gt; poslouží
k inicializaci&amp;nbsp; &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ProxyScheduleru&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ProxyScheduler&lt;/a&gt; našeho &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduleru&lt;/a&gt; je
TPL scheduler pro &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(v=vs.110).aspx"&gt;TaskFactory&lt;/a&gt;.
Tásky vytvořené v testTaskFactory zpracuje &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduler&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;m_testTaskFactory = new TaskFactory(ProxyScheduler.AsTplScheduler());&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Vše o vzájemných vztazích mezi “proxy” schedulery a “reálných” schedulery &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;naleznete
v prvním díle seriálu&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Přišla také chvíle, abych vysvětlil, proč existuje třída IAutonomousSchedulerTests
a upřesnil terminologii v knihovně &lt;a href="https://bitbucket.org/renestein/rstein.async/src/723f7a7e9ca83a228e29af3565ff82e560a9ed5d?at=master"&gt;RStein.Async&lt;/a&gt;.
Ve třídě IAutonomousSchedulerTests se nacházejí testy, kterými musí projít všechny
autonomní schedulery. Jako &lt;strong&gt;autonomní scheduler &lt;/strong&gt;označuju takový scheduler,
který po svém vytvoření ihned zpracovává předané tásky a nevyžaduje ze strany aplikace
již žádnou další konfiguraci ani podporu při zpracování tásků. Z schedulerů, které
prozatím známe, můžeme za autonomní schedulery označit právě &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduler&lt;/a&gt; nebo &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;CurrentThreadScheduler&lt;/a&gt;,
který jsme viděli &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;v
prvním díle seriálu&lt;/a&gt;. Naopak &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+2+Ndash+Boost+ASIO+V+Net+A+IoServiceScheduler.aspx"&gt;IoServiceScheduler&lt;/a&gt; není
autonomní scheduler, protože po svém vytvoření čeká na to, až mu aplikace propůjčí
pro vyřizování tásků thread tím, že zavolá jednu z jeho metod Run, RunOne, Poll nebo
PollOne.
&lt;/p&gt;
&lt;p&gt;
Nejprve otestujeme konstruktory &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduleru&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Jestliže není předán &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+2+Ndash+Boost+ASIO+V+Net+A+IoServiceScheduler.aspx"&gt;IoServiceScheduler&lt;/a&gt;,
musí být vyvolána výjimka.
&lt;/p&gt;
&lt;script src="https://gist.github.com/renestein/ff29cf0892ec61f9dfed.js"&gt;&lt;/script&gt;
&lt;p&gt;
Počet threadů v threadpoolu nesmí být nulový a ani neumíme vytvořit záporný počet
threadů.
&lt;/p&gt;
&lt;script src="https://gist.github.com/renestein/75fd796575d1633cd7cc.js"&gt;&lt;/script&gt;
&lt;p&gt;
Jak jsem před chvílí vysvětlil, &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduler&lt;/a&gt; je
jedním z autonomích schedulerů,&amp;nbsp; a proto musí projít všemi testy pro autonomní
schedulery. Většinu testů jsme viděli při testování &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;CurrentThreadScheduleru&lt;/a&gt;,
a proto&amp;nbsp; u následujících testů jen jen shrnu, že v jednom testu ověřujeme bezproblémové
vyřízení jednoho tásku a v dalším testu zpracování většího množství tásků.
&lt;/p&gt;
&lt;script src="https://gist.github.com/renestein/f9061d41a0d0d8d91164.js"&gt;&lt;/script&gt;
&lt;p&gt;
Následující test je zajímavější, protože ověřuje, že když zavoláme metodu Dispose,
tak &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduler&lt;/a&gt; vyřídí
všechny zbývající tásky a teprvé poté metoda Dispose ukončí činnost scheduleru. O
metodě Dispose u schedulerů chci ještě v nějakém dalším díle napsat více, protože
deterministické ukončení činnosti různých schedulerů, kdy každý může mít zcela odlišné
chování, je jeden z nejméně příjemných úkolů a bez ohledu na to, jaké řešení zvolíte,
nezbavíte sebe ani ostatní, kteří schedulery ve svých aplikacích pouze používají,
všech problémů. Jsem v čím dál silnějším pokušení některé hraniční scénáře, kdy klient
nerespektuje životní cyklus schedulerů a tásků,&amp;nbsp; přesunout do temné říše nedefinovaného
chování.&lt;img class="wlEmoticon wlEmoticon-smile" alt="Vesel&amp;yacute; obličej" src="$wlEmoticon-smile2.png"&gt; U &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;ThreadPoolScheduleru&lt;/a&gt; ale
nic takového nehrozí, i když byste měli mít nepříjemné mrazení z toho, že se snažíte
likvidovat scheduler, aniž byste si byli jisti, že před voláním metody Dispose vyřídil
všechny tásky.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;script src="https://gist.github.com/renestein/69a155f9c6b865d2beb5.js"&gt;&lt;/script&gt;
&lt;p&gt;
Asynchronní test &lt;em&gt;Dispose_When_Tasks_Are_Queued_Then_All_Tasks_Are_Executed &lt;/em&gt;spadá
pod ty užitečné, ale ne zrovna bezpečné testy, o kterých &lt;a href="http://blog.renestein.net/Task+Parallel+Library+A+RStein+Async+1+Popis+Zaacutekladniacutech+T%C5%99iacuted+A+Obchaacutezeniacute+Omezeniacute+V+TPL.aspx"&gt;jsem
už také psal&lt;/a&gt;. Vygenerujeme tisíc tásků, zařadíme je ke zpracování, ale každý tásk
je zablokován do té doby, dokud nestornujeme &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.cancellationtokensource(v=vs.110).aspx"&gt;CancellationTokenSource&lt;/a&gt; s
názvem &lt;em&gt;waitForSignalCts.&lt;/em&gt; Za storno odpovídá metoda &lt;a href="http://msdn.microsoft.com/en-us/library/hh194678(v=vs.110).aspx"&gt;CancelAfter&lt;/a&gt;,
která stornuje &lt;em&gt;&lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken(v=vs.110).aspx"&gt;CancellationToken&lt;/a&gt; po
uplynutí stanoveného času. My stornujeme &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken(v=vs.110).aspx"&gt;CancellationToken&lt;/a&gt; po
uplynutí jedné sekundy od zařazení tásků ke zpracování. Ihned po zavolání metody &lt;a href="http://msdn.microsoft.com/en-us/library/hh194678(v=vs.110).aspx"&gt;CancelAfter&lt;/a&gt; zavoláme
metodu Dispose scheduleru a ověříme, že všechny vygenerované a scheduleru předané
tásky byly zpracovány. 
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
Kdyby to snad někomu ušlo, upozorním, že &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.cancellationtokensource(v=vs.110).aspx"&gt;CancellationTokenSource&lt;/a&gt; používáme
ke komunikaci mezi thready. &lt;strong&gt;Žádný tásk nestornujeme, jen použijeme &lt;/strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken(v=vs.110).aspx"&gt;&lt;strong&gt;CancellationToken&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; k
částečné synchronizaci mezi kódem v testu a kódem v táscích.&lt;/strong&gt; Taková rychlá
náhrada za synchronizační primitivu &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.manualreseteventslim(v=vs.110).aspx"&gt;ManualResetEventSlim&lt;/a&gt; nebo &lt;a href="http://msdn.microsoft.com/en-us/library/System.Threading(v=vs.110).aspx"&gt;její
příbuzné&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Psal jsem, že test není bezpečný. V testu je totiž “race condition”, protože by teoreticky
mohlo dojít k tomu, že metoda Dispose bude zavolána teprve poté, co jsou všechny tásky
v scheduleru už vyřízeny. Takový test by opět prošel, ale ověřil&amp;nbsp; by jen chování,
které už ověřuje test &lt;em&gt;WithTaskFactory_When_Tasks_Are_Queued_Then_All_Tasks_Are_Executed&lt;/em&gt;.
V této fázi vývoje knihovny &lt;a href="https://bitbucket.org/renestein/rstein.async/src/723f7a7e9ca83a228e29af3565ff82e560a9ed5d?at=master"&gt;RStein.Async&lt;/a&gt; dokážu
i s takovým špinavým testem sdílet jednu “solution” ve Visual Studiu. &lt;img class="wlEmoticon wlEmoticon-smile" alt="Vesel&amp;yacute; obličej" src="$wlEmoticon-smile2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
Další testy už jsou pro všechny schedulery společné a můžete se na ně &lt;a href="https://bitbucket.org/renestein/rstein.async/src/1469778a484f61a06b287a3371bfa0088ceac16b/RStein.Async.Tests/ITaskSchedulerTests.cs?at=master#cl-33"&gt;podívat
sami&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Můžeme být spokojeni, všechny testy jsou zelené.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Open-Live-Writer/8a34d9512872_AFDB/Image_2.png"&gt;&lt;img width="244" height="84" title="Image" style="display: inline; background-image: none;" alt="Image" src="http://blog.renestein.net/content/binary/Open-Live-Writer/8a34d9512872_AFDB/Image_thumb.png" border="0"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
V dalším díle si pořídíme zajímavý přírůstek do rodiny schedulerů s názvem StrandScheduler.
Plným jménem &lt;em&gt;StrandSchedulerDecorator&lt;/em&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=4248081e-7a49-49ae-bd23-7a241892a7e0" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,4248081e-7a49-49ae-bd23-7a241892a7e0.aspx</comments>
      <category>C#</category>
      <category>Návrhové vzory</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=10792dd8-6b85-49f8-bd87-b3a91dfa5b6f</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,10792dd8-6b85-49f8-bd87-b3a91dfa5b6f.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,10792dd8-6b85-49f8-bd87-b3a91dfa5b6f.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=10792dd8-6b85-49f8-bd87-b3a91dfa5b6f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
 
</p>
        <p>
Pro ty z vás, kdo jste se mě ptali na záznam přednášky z MS Festu, mám (snad dobrou)
zprávu. Záznam přednášky je od tohoto týdne dostupný na webu WUG.  O “snad dobré”
zprávě píšu proto, že jsme sám nenašel odvahu se na sebe podívat.<img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Zznam-pednky-z-MS-Festu-2012_6724/wlEmoticon-smile_2.png" /></p>
        <p>
          <a title="http://www.wug.cz/zaznamy/125-MS-Fest-2012-DI-v-NET-bez-pover-iluzi-a-frikulinskeho-nadseni" href="http://www.wug.cz/zaznamy/125-MS-Fest-2012-DI-v-NET-bez-pover-iluzi-a-frikulinskeho-nadseni">http://www.wug.cz/zaznamy/125-MS-Fest-2012-DI-v-NET-bez-pover-iluzi-a-frikulinskeho-nadseni</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Prezentace+Z+P%C5%99ednaacutescaronky+Na+MS+Festu+2012+DI+V+NET+Bez+Pov%C4%9Br+Iluziacute+A+Frikuliacutenskeacuteho+Nadscaroneniacute.aspx" target="_blank">Materiály
k přednášce.</a>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=10792dd8-6b85-49f8-bd87-b3a91dfa5b6f" />
      </body>
      <title>Z&amp;aacute;znam předn&amp;aacute;&amp;scaron;ky z MS Festu 2012 -  Dependency injection v .NET bez pověr, iluz&amp;iacute; a frikul&amp;iacute;nsk&amp;eacute;ho nad&amp;scaron;en&amp;iacute;</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,10792dd8-6b85-49f8-bd87-b3a91dfa5b6f.aspx</guid>
      <link>http://blog.renestein.net/Zaacuteznam+P%c5%99ednaacutescaronky+Z+MS+Festu+2012+Dependency+Injection+V+NET+Bez+Pov%c4%9br+Iluziacute+A+Frikuliacutenskeacuteho+Nadscaroneniacute.aspx</link>
      <pubDate>Sat, 23 Mar 2013 06:25:46 GMT</pubDate>
      <description>&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Pro ty z vás, kdo jste se mě ptali na záznam přednášky z MS Festu, mám (snad dobrou)
zprávu. Záznam přednášky je od tohoto týdne dostupný na webu WUG.&amp;nbsp; O “snad dobré”
zprávě píšu proto, že jsme sám nenašel odvahu se na sebe podívat.&lt;img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Zznam-pednky-z-MS-Festu-2012_6724/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a title="http://www.wug.cz/zaznamy/125-MS-Fest-2012-DI-v-NET-bez-pover-iluzi-a-frikulinskeho-nadseni" href="http://www.wug.cz/zaznamy/125-MS-Fest-2012-DI-v-NET-bez-pover-iluzi-a-frikulinskeho-nadseni"&gt;http://www.wug.cz/zaznamy/125-MS-Fest-2012-DI-v-NET-bez-pover-iluzi-a-frikulinskeho-nadseni&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Prezentace+Z+P%C5%99ednaacutescaronky+Na+MS+Festu+2012+DI+V+NET+Bez+Pov%C4%9Br+Iluziacute+A+Frikuliacutenskeacuteho+Nadscaroneniacute.aspx" target="_blank"&gt;Materiály
k přednášce.&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=10792dd8-6b85-49f8-bd87-b3a91dfa5b6f" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,10792dd8-6b85-49f8-bd87-b3a91dfa5b6f.aspx</comments>
      <category>.NET Framework</category>
      <category>C#</category>
      <category>Návrhové vzory</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=e8badc0b-2c3d-481c-ba17-9d89535bf19b</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,e8badc0b-2c3d-481c-ba17-9d89535bf19b.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,e8badc0b-2c3d-481c-ba17-9d89535bf19b.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=e8badc0b-2c3d-481c-ba17-9d89535bf19b</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
 
</p>
        <p>
          <a href="http://www.vbnet.cz/blog--tomas.aspx" target="_blank">Tomáše Herceg</a> &amp;
comp. opět po roce uspořádali další ročník konference <a href="http://www.ms-fest.cz/" target="_blank">MS
Fest</a>. A musím hned dodat, že z mého pohledu velmi povedený <a href="http://www.ms-fest.cz/" target="_blank">MS
Fest</a>, jehož organizace nikde neskřípala a na kterém jsme se cítil příjemně. Tímto
organizátorům ještě jednou děkuju za skvělou organizaci konference a za veškerý servis,
který poskytovali účastníkům konference i přednášejícím.
</p>
        <p>
Na MS Festu jsme měl přednášku nazvanou Dependency injection v .Net Frameworku bez
pověr, iluzí a frikulínského nadšení. 
<br />
Sice jsem se jako každý rok po domluvě s organizátory na tématu přednášky dodatečně
zděsil, že na přednášku mám jen 60 minut, a těsně před konferencí se stovkami účastníků
jsme musel nahodit svůj přídavný a životní energii rychle spalující extrovertní pohon,
ale samotná přednáška probíhala <a href="http://blog.renestein.net/Prezentace+Z+MS+Festu+2011+A+Stru%C4%8Dnyacute+Komentaacute%C5%99.aspx" target="_blank">oproti
minulému roku</a> poklidně. Nemyslete si, já  teprve po minulém ročníku MS Festu
dovedu ocenit, jaké je to blaho,  když s vámi v půlce probíhající  přednášky
nezačne zuřivě diskutovat oponent z Nokie. <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Prezentace-z-pednky-na-MS-festu-2012_AEAD/wlEmoticon-smile_2.png" /></p>
        <p>
Nabízel jsem <a href="https://plus.google.com/u/0/100048458679392044814/posts/3ZJsehWB6ts" target="_blank">tyto
přednášky</a>.
</p>
        <p>
Tomáš Herceg mi původně v programu navrhl dvě přednášky, ale já jsme měl čas jen na
přípravu jedné přednášky <strong>a vybral jsem tu, která dostala nejvíce hlasů.</strong></p>
        <div style="width: 400px">
          <blockquote class="twitter-tweetn" width="350">
            <p>
              <a href="https://twitter.com/search/%23msfest">#msfest</a> je dobra akce, ale chtelo
by to vice narocna temata, jako bylo SQL Internals
</p>
— Michal Těhník (@MicTech) <a href="https://twitter.com/MicTech/status/275212740405112832" data-datetime="2012-12-02T12:20:05+00:00">December
2, 2012</a></blockquote>
          <blockquote class="twitter-tweetn">
            <p>
@<a href="https://twitter.com/mictech">mictech</a> Pak je třeba pro ně hlasovat. @<a href="https://twitter.com/hercegtomas">hercegtomas</a> po
mně chtěl i nabídnutou přenášku "TPL pro (cont) <a title="http://tl.gd/k7743o" href="http://t.co/OvLERrAd">tl.gd/k7743o</a></p>
— Rene Stein (@renestein) <a href="https://twitter.com/renestein/status/275218348361531392" data-datetime="2012-12-02T12:42:22+00:00">December
2, 2012</a></blockquote>
          <blockquote class="twitter-tweetn" data-in-reply-to="275218348361531392">
            <p>
@<a href="https://twitter.com/renestein">renestein</a> @<a href="https://twitter.com/hercegtomas">hercegtomas</a> Hlasoval
jsem, ale evidetne patrim k minorite. <a href="https://twitter.com/search/%23msfest">#msfest</a></p>
— Michal Těhník (@MicTech) <a href="https://twitter.com/MicTech/status/275246332359360513" data-datetime="2012-12-02T14:33:34+00:00">December
2, 2012</a></blockquote>
        </div>
        <p>
Nevím, jaká je poptávka po pokročilejších/hard core přednáškách. Jak jsem psal na
Twitteru, sám bych raději přednášel o “Task parallel library  pro pokročilé”,
ještě raději o skrytých pokladech v <a href="http://blog.renestein.net/Hraacutetky+S+Reaktivniacutem+Frameworkem+RX+Extenze.aspx" target="_blank">RX
Frameworku</a>, ale RX si již dříve zamluvil Jarda Jírava. Bavilo by mě také přednášet
o <a href="http://blog.renestein.net/C%20Kontrola%20Existence%20Vlastnosti%20U%20Typu%20Dynamic%20Bez%20Vyvolaacuteniacute%20Vyacutejimky%20RuntimeBinderException.aspx" target="_blank">specialitkách
typu dynamic</a>, mohli bychom se pobavit o klíčových slovech async/await v netradičních
kontextech, nebo bychom mohli napsat dalšího hostitele .Net Frameworku. To je alespoň
malý výběr z témat, která mi jsou blízká, protože jsem podobné  vývojářské specialitky
řešil pro různé firmy u nás i v zahraničí. Nevím, jaká by ale byla po těchto tématech
na MS Festu poptávka, protože povídat si v potemnělé posluchárně jen pro sebe nebo
prezentovat pro maximálně deset dalších  lidí má své kouzlo, ale - při vší úctě
- intimní atmosféru mám raději s jinými než vývojářskými  kulisami a aktéry. <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Prezentace-z-pednky-na-MS-festu-2012_AEAD/wlEmoticon-smile_2.png" /></p>
        <p>
Slíbená prezentace:<br /></p>
        <iframe style="border-bottom: #ccc 0px solid; border-left: #ccc 1px solid; margin-bottom: 5px; border-top: #ccc 1px solid; border-right: #ccc 1px solid" height="356" marginheight="0" src="http://www.slideshare.net/slideshow/embed_code/15464467" frameborder="0" width="427" marginwidth="0" scrolling="no" mozallowfullscreen="mozallowfullscreen" webkitallowfullscreen="webkitallowfullscreen" allowfullscreen="allowfullscreen">
        </iframe>
        <div style="margin-bottom: 5px">
          <strong>
            <a title="Depdendency injection v .Net Frameworku" href="http://www.slideshare.net/renestein1/depdendency-injection-v-net-frameworku" target="_blank">Dependency
injection v .Net Frameworku</a>
          </strong>from <strong><a href="http://www.slideshare.net/renestein1" target="_blank">René
Stein</a></strong></div>
        <p>
          <a href="https://bitbucket.org/renestein/rstein.msfest.cookbookf" target="_blank">Doprovodný
kód je na Bitbucketu:</a>
          <br />
        </p>
        <p>
Díky za to, že jste na mou přednášku přišli. A děkuju za hodnocení přednášky, moc
jste mě potěšili. <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Prezentace-z-pednky-na-MS-festu-2012_AEAD/wlEmoticon-smile_2.png" /></p>
        <p>
 
</p>
        <p>
P .S. Ještě málá terminologická poznámka, proč používám slovo “kontajner”, a ne kontejner,
na což se mě ptal už Tomáš Herceg po zaslání anotace.<br /></p>
        <p>
          <em>Oficiálně [myšleno  - slovo kontajner žádný speciální význam] nemá – dokonce
myslím ÚJČ slovo kontajner ani neuznává.</em>
        </p>
        <p>
          <em>Viděl jsem, že se ale v ČR slovo kontajner docela vžilo a snažím se jeho použitím
odlišit od konotací „kontejneru“ – u kterého mnoho lidí vidí spojitost s odpadky.:)</em>
        </p>
        <p>
P. P. S. A ještě děkuju <a href="http://rarous.net/weblog/" target="_blank">Alešovi
Roubíčkovi</a> za to, že si ochotně pročetl mou prezentaci a upozornil mě na místa,
která by si zasloužila nějaké upřesnění.
</p>
        <p>
P.P.P.S. Mrzí mě jediná věc. Na svých přednáškách většinou nezvětšuju písmo, na této
přednášce jsem písmo ve Visual Studiu zvětšil přesně tak, jako to měl Tomáš Herceg
na první přednášce, a při výkladu mě dost mátlo, že na obrazovce je vidět málo kódu,
i když jsem měl z domova vyzkoušeno, že by kód měl být vidět bez problémů. Místo toho, 
abych VS přepnul na celou obrazovku, tak jsem skroloval a v duchu se divil, proč je
toho vidět tak málo. Takové momentální okno přednášejícího, který zapomněl, co udělal
s fontem o přestávce. A ještě – poté, co mi spadl mikrofon a já si jej znovu nasadil,
tak prý bylo slyšet hlavně v zadních řadách praskání a jiné pazvuky. Já jsem bohužel
nic neslyšel a nikdo z posluchačů neprotestoval.
</p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=e8badc0b-2c3d-481c-ba17-9d89535bf19b" />
      </body>
      <title>Prezentace z předn&amp;aacute;&amp;scaron;ky na MS festu 2012 - DI v .NET bez pověr, iluz&amp;iacute; a frikul&amp;iacute;nsk&amp;eacute;ho nad&amp;scaron;en&amp;iacute;</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,e8badc0b-2c3d-481c-ba17-9d89535bf19b.aspx</guid>
      <link>http://blog.renestein.net/Prezentace+Z+P%c5%99ednaacutescaronky+Na+MS+Festu+2012+DI+V+NET+Bez+Pov%c4%9br+Iluziacute+A+Frikuliacutenskeacuteho+Nadscaroneniacute.aspx</link>
      <pubDate>Mon, 03 Dec 2012 12:25:14 GMT</pubDate>
      <description>&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.vbnet.cz/blog--tomas.aspx" target="_blank"&gt;Tomáše Herceg&lt;/a&gt; &amp;amp;
comp. opět po roce uspořádali další ročník konference &lt;a href="http://www.ms-fest.cz/" target="_blank"&gt;MS
Fest&lt;/a&gt;. A musím hned dodat, že z mého pohledu velmi povedený &lt;a href="http://www.ms-fest.cz/" target="_blank"&gt;MS
Fest&lt;/a&gt;, jehož organizace nikde neskřípala a na kterém jsme se cítil příjemně. Tímto
organizátorům ještě jednou děkuju za skvělou organizaci konference a za veškerý servis,
který poskytovali účastníkům konference i přednášejícím.
&lt;/p&gt;
&lt;p&gt;
Na MS Festu jsme měl přednášku nazvanou Dependency injection v .Net Frameworku bez
pověr, iluzí a frikulínského nadšení. 
&lt;br&gt;
Sice jsem se jako každý rok po domluvě s organizátory na tématu přednášky dodatečně
zděsil, že na přednášku mám jen 60 minut, a těsně před konferencí se stovkami účastníků
jsme musel nahodit svůj přídavný a životní energii rychle spalující extrovertní pohon,
ale samotná přednáška probíhala &lt;a href="http://blog.renestein.net/Prezentace+Z+MS+Festu+2011+A+Stru%C4%8Dnyacute+Komentaacute%C5%99.aspx" target="_blank"&gt;oproti
minulému roku&lt;/a&gt; poklidně. Nemyslete si, já&amp;nbsp; teprve po minulém ročníku MS Festu
dovedu ocenit, jaké je to blaho,&amp;nbsp; když s vámi v půlce probíhající&amp;nbsp; přednášky
nezačne zuřivě diskutovat oponent z Nokie. &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Prezentace-z-pednky-na-MS-festu-2012_AEAD/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
Nabízel jsem &lt;a href="https://plus.google.com/u/0/100048458679392044814/posts/3ZJsehWB6ts" target="_blank"&gt;tyto
přednášky&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Tomáš Herceg mi původně v programu navrhl dvě přednášky, ale já jsme měl čas jen na
přípravu jedné přednášky &lt;strong&gt;a vybral jsem tu, která dostala nejvíce hlasů.&lt;/strong&gt; 
&lt;/p&gt;
&lt;div style="width: 400px"&gt;
&lt;blockquote class="twitter-tweetn" width="350"&gt; 
&lt;p&gt;
&lt;a href="https://twitter.com/search/%23msfest"&gt;#msfest&lt;/a&gt; je dobra akce, ale chtelo
by to vice narocna temata, jako bylo SQL Internals
&lt;/p&gt;
— Michal Těhník (@MicTech) &lt;a href="https://twitter.com/MicTech/status/275212740405112832" data-datetime="2012-12-02T12:20:05+00:00"&gt;December
2, 2012&lt;/a&gt;&lt;/blockquote&gt; &lt;blockquote class="twitter-tweetn"&gt; 
&lt;p&gt;
@&lt;a href="https://twitter.com/mictech"&gt;mictech&lt;/a&gt; Pak je třeba pro ně hlasovat. @&lt;a href="https://twitter.com/hercegtomas"&gt;hercegtomas&lt;/a&gt; po
mně chtěl i nabídnutou přenášku "TPL pro (cont) &lt;a title="http://tl.gd/k7743o" href="http://t.co/OvLERrAd"&gt;tl.gd/k7743o&lt;/a&gt;
&lt;/p&gt;
— Rene Stein (@renestein) &lt;a href="https://twitter.com/renestein/status/275218348361531392" data-datetime="2012-12-02T12:42:22+00:00"&gt;December
2, 2012&lt;/a&gt;&lt;/blockquote&gt; &lt;blockquote class="twitter-tweetn" data-in-reply-to="275218348361531392"&gt; 
&lt;p&gt;
@&lt;a href="https://twitter.com/renestein"&gt;renestein&lt;/a&gt; @&lt;a href="https://twitter.com/hercegtomas"&gt;hercegtomas&lt;/a&gt; Hlasoval
jsem, ale evidetne patrim k minorite. &lt;a href="https://twitter.com/search/%23msfest"&gt;#msfest&lt;/a&gt;
&lt;/p&gt;
— Michal Těhník (@MicTech) &lt;a href="https://twitter.com/MicTech/status/275246332359360513" data-datetime="2012-12-02T14:33:34+00:00"&gt;December
2, 2012&lt;/a&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;p&gt;
Nevím, jaká je poptávka po pokročilejších/hard core přednáškách. Jak jsem psal na
Twitteru, sám bych raději přednášel o “Task parallel library&amp;nbsp; pro pokročilé”,
ještě raději o skrytých pokladech v &lt;a href="http://blog.renestein.net/Hraacutetky+S+Reaktivniacutem+Frameworkem+RX+Extenze.aspx" target="_blank"&gt;RX
Frameworku&lt;/a&gt;, ale RX si již dříve zamluvil Jarda Jírava. Bavilo by mě také přednášet
o &lt;a href="http://blog.renestein.net/C%20Kontrola%20Existence%20Vlastnosti%20U%20Typu%20Dynamic%20Bez%20Vyvolaacuteniacute%20Vyacutejimky%20RuntimeBinderException.aspx" target="_blank"&gt;specialitkách
typu dynamic&lt;/a&gt;, mohli bychom se pobavit o klíčových slovech async/await v netradičních
kontextech, nebo bychom mohli napsat dalšího hostitele .Net Frameworku. To je alespoň
malý výběr z témat, která mi jsou blízká, protože jsem podobné&amp;nbsp; vývojářské specialitky
řešil pro různé firmy u nás i v zahraničí. Nevím, jaká by ale byla po těchto tématech
na MS Festu poptávka, protože povídat si v potemnělé posluchárně jen pro sebe nebo
prezentovat pro maximálně deset dalších&amp;nbsp; lidí má své kouzlo, ale - při vší úctě
- intimní atmosféru mám raději s jinými než vývojářskými&amp;nbsp; kulisami a aktéry. &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Prezentace-z-pednky-na-MS-festu-2012_AEAD/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
Slíbená prezentace:&lt;br&gt;
&lt;/p&gt;
&lt;iframe style="border-bottom: #ccc 0px solid; border-left: #ccc 1px solid; margin-bottom: 5px; border-top: #ccc 1px solid; border-right: #ccc 1px solid" height="356" marginheight="0" src="http://www.slideshare.net/slideshow/embed_code/15464467" frameborder="0" width="427" marginwidth="0" scrolling="no" mozallowfullscreen webkitallowfullscreen allowfullscreen&gt;
&lt;/iframe&gt;
&lt;div style="margin-bottom: 5px"&gt;&lt;strong&gt;&lt;a title="Depdendency injection v .Net Frameworku" href="http://www.slideshare.net/renestein1/depdendency-injection-v-net-frameworku" target="_blank"&gt;Dependency
injection v .Net Frameworku&lt;/a&gt; &lt;/strong&gt;from &lt;strong&gt;&lt;a href="http://www.slideshare.net/renestein1" target="_blank"&gt;René
Stein&lt;/a&gt;&lt;/strong&gt; 
&lt;/div&gt;
&lt;p&gt;
&lt;a href="https://bitbucket.org/renestein/rstein.msfest.cookbookf" target="_blank"&gt;Doprovodný
kód je na Bitbucketu:&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
Díky za to, že jste na mou přednášku přišli. A děkuju za hodnocení přednášky, moc
jste mě potěšili. &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Prezentace-z-pednky-na-MS-festu-2012_AEAD/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
P .S. Ještě málá terminologická poznámka, proč používám slovo “kontajner”, a ne kontejner,
na což se mě ptal už Tomáš Herceg po zaslání anotace.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Oficiálně [myšleno&amp;nbsp; - slovo kontajner žádný speciální význam] nemá – dokonce
myslím ÚJČ slovo kontajner ani neuznává.&lt;/em&gt; 
&lt;p&gt;
&lt;em&gt;Viděl jsem, že se ale v ČR slovo kontajner docela vžilo a snažím se jeho použitím
odlišit od konotací „kontejneru“ – u kterého mnoho lidí vidí spojitost s odpadky.:)&lt;/em&gt; 
&lt;p&gt;
P. P. S. A ještě děkuju &lt;a href="http://rarous.net/weblog/" target="_blank"&gt;Alešovi
Roubíčkovi&lt;/a&gt; za to, že si ochotně pročetl mou prezentaci a upozornil mě na místa,
která by si zasloužila nějaké upřesnění.
&lt;/p&gt;
&lt;p&gt;
P.P.P.S. Mrzí mě jediná věc. Na svých přednáškách většinou nezvětšuju písmo, na této
přednášce jsem písmo ve Visual Studiu zvětšil přesně tak, jako to měl Tomáš Herceg
na první přednášce, a při výkladu mě dost mátlo, že na obrazovce je vidět málo kódu,
i když jsem měl z domova vyzkoušeno, že by kód měl být vidět bez problémů. Místo toho,&amp;nbsp;
abych VS přepnul na celou obrazovku, tak jsem skroloval a v duchu se divil, proč je
toho vidět tak málo. Takové momentální okno přednášejícího, který zapomněl, co udělal
s fontem o přestávce. A ještě – poté, co mi spadl mikrofon a já si jej znovu nasadil,
tak prý bylo slyšet hlavně v zadních řadách praskání a jiné pazvuky. Já jsem bohužel
nic neslyšel a nikdo z posluchačů neprotestoval.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=e8badc0b-2c3d-481c-ba17-9d89535bf19b" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,e8badc0b-2c3d-481c-ba17-9d89535bf19b.aspx</comments>
      <category>.NET Framework</category>
      <category>C#</category>
      <category>Entity Framework</category>
      <category>Návrhové vzory</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=dac3a930-3326-4521-a8b1-7e84ae709519</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,dac3a930-3326-4521-a8b1-7e84ae709519.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,dac3a930-3326-4521-a8b1-7e84ae709519.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=dac3a930-3326-4521-a8b1-7e84ae709519</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
 
</p>
        <p>
          <font color="#ff0000">Aktualizace 4. 12. 2012 – kurz Objektovými principy a návrhovými
vzory řízený design a vývoj kvalitních aplikací 1 je zcela obsazen.</font>
        </p>
        <p>
Opět bych vás rád pozval mé kurzy. Jak jste si asi všimli, tento rok “podzimní” termíny
kurzů vyhlašuju kvůli různým peripetiím o něco později, takže místo podzimu se s některými
z vás uvidím netradičně až v zimě. Snad to nevadí. 
</p>
        <p>
Také již tradičně připomenu, že je možné si objednat inhouse (ve vaší firmě uskutečněnou)
variantu těchto kurzů i se domluvit na zcela jiné osnově vystavěné z <a href="http://renestein.net/Nabidka.aspx#konzultace" target="_blank">témat,
o kterých něco vím a jejichž výběr naleznete na mých stránkách</a>. Všechny dotazy
k veřejným i inhouse kurzům rádi zodpovíme na emailu <a href="mailto:rene@renestein.net">rene@renestein.net</a> (můj
email) nebo na emailu <a href="mailto:petra@renestein.net">petra@renestein.net</a> (Petra
Steinová, která rychleji a lépe než já odpoví na dotazy týkající se organizace veřejných
i inhouse kurzů). 
</p>
        <p>
          <b>Veřejný kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních
aplikací 1</b>
          <font color="#ff0000"> <font style=""><font style="">- <font style="">kurz
je obsazen</font></font></font></font>
        </p>
        <p>
Datum konání kurzu: <strong>10. - 12. 12. 2012</strong></p>
        <p>
Místo konání<strong>:</strong></p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.tutor.cz%2f">Školící
středisko Tutor</a>
        </p>
        <p>
U Půjčovny 2<br />
110 00 Praha 1 
</p>
        <p>
          <em>Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.</em>
        </p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fNabidka.aspx%2523skoleni">Podrobné
informace o kurzu a možnost přihlásit se na kurz</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fSkoleni-UML-OOP-Navrhove-vzory-1.aspx">Program
kurzu</a>
          <br />
        </p>
        <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.renestein.net%2fOhlasy-Ucastniku-Na-Kurzy.aspx">Výběr
z ohlasů na kurzy</a>
        <br />
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2frenestein.net%2fCasto-Kladene-Dotazy-Kurzy-FAQ.aspx">FAQ
- často kladené dotazy ke kurzům</a>
          <hr />
        </p>
        <p>
          <b>Veřejný kurz Základy objektově orientovaného návrhu a vývoje (UML 0)</b>
        </p>
        <p>
Datum konání kurzu: <b>14. - 16. 1. 2013</b></p>
        <p>
Místo konání<strong>:</strong></p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.tutor.cz%2f">Školící
středisko Tutor</a>
        </p>
        <p>
U Půjčovny 2<br />
110 00 Praha 1 
</p>
        <p>
          <em>Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.</em>
        </p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2frenestein.net%2fNabidka.aspx%23skoleniOOP0">Podrobné
informace o kurzu a možnost přihlásit se na kurz</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2frenestein.net%2fSkoleni-Zaklady-Objektove-Orientovaneho-Navrhu-UML-0.aspx">Program
kurzu</a>
          <br />
        </p>
        <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.renestein.net%2fOhlasy-Ucastniku-Na-Kurzy.aspx">Výběr
z ohlasů na kurzy</a>
        <br />
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2frenestein.net%2fCasto-Kladene-Dotazy-Kurzy-FAQ.aspx">FAQ 
- často kladené dotazy ke kurzům</a>
        </p>
        <p>
 
</p>
        <p>
          <hr />
        </p>
        <p>
          <b>Veřejný kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních
aplikací 2</b>
        </p>
        <p>
Datum konání kurzu:  <strong>21. - 23. 1. 2013</strong></p>
        <p>
Místo konání<strong>:</strong></p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.tutor.cz%2f">Školící
středisko Tutor</a>
        </p>
        <p>
U Půjčovny 2<br />
110 00 Praha 1 
</p>
        <p>
          <em>Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.</em>
        </p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.renestein.net%2fNabidka.aspx%23SkoleniOOP2">Podrobné
informace o kurzu a možnost přihlásit se na kurz</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.renestein.net%2fSkoleni-Navrhove-vzory-2.aspx">Program
kurzu</a>
          <br />
          <br />
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.renestein.net%2fOhlasy-Ucastniku-Na-Kurzy.aspx">Výběr
z ohlasů na kurzy</a>
          <br />
          <br />
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2frenestein.net%2fCasto-Kladene-Dotazy-Kurzy-FAQ.aspx">FAQ
- často kladené dotazy ke kurzům</a>
        </p>
        <p>
Těším se na shledání na kurzu.
</p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=dac3a930-3326-4521-a8b1-7e84ae709519" />
      </body>
      <title>Pozv&amp;aacute;nka na m&amp;eacute; kurzy v prosinci 2012 a lednu 2013 (Update 4. 12. 2012)</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,dac3a930-3326-4521-a8b1-7e84ae709519.aspx</guid>
      <link>http://blog.renestein.net/Pozvaacutenka+Na+Meacute+Kurzy+V+Prosinci+2012+A+Lednu+2013+Update+4+12+2012.aspx</link>
      <pubDate>Wed, 26 Sep 2012 11:53:24 GMT</pubDate>
      <description>&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;font color="#ff0000"&gt;Aktualizace 4. 12. 2012 – kurz Objektovými principy a návrhovými
vzory řízený design a vývoj kvalitních aplikací 1 je zcela obsazen.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Opět bych vás rád pozval mé kurzy. Jak jste si asi všimli, tento rok “podzimní” termíny
kurzů vyhlašuju kvůli různým peripetiím o něco později, takže místo podzimu se s některými
z vás uvidím netradičně až v zimě. Snad to nevadí. 
&lt;/p&gt;
&lt;p&gt;
Také již tradičně připomenu, že je možné si objednat inhouse (ve vaší firmě uskutečněnou)
variantu těchto kurzů i se domluvit na zcela jiné osnově vystavěné z &lt;a href="http://renestein.net/Nabidka.aspx#konzultace" target="_blank"&gt;témat,
o kterých něco vím a jejichž výběr naleznete na mých stránkách&lt;/a&gt;. Všechny dotazy
k veřejným i inhouse kurzům rádi zodpovíme na emailu &lt;a href="mailto:rene@renestein.net"&gt;rene@renestein.net&lt;/a&gt; (můj
email) nebo na emailu &lt;a href="mailto:petra@renestein.net"&gt;petra@renestein.net&lt;/a&gt; (Petra
Steinová, která rychleji a lépe než já odpoví na dotazy týkající se organizace veřejných
i inhouse kurzů). 
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;Veřejný kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních
aplikací 1&lt;/b&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&lt;font style=""&gt; &lt;font style=""&gt;- &lt;font style=""&gt;kurz
je obsazen&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt; 
&lt;p&gt;
Datum konání kurzu: &lt;strong&gt;10. - 12. 12. 2012&lt;/strong&gt; 
&lt;p&gt;
Místo konání&lt;strong&gt;:&lt;/strong&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.tutor.cz%2f"&gt;Školící
středisko Tutor&lt;/a&gt; 
&lt;p&gt;
U Půjčovny 2&lt;br&gt;
110 00 Praha 1 
&lt;p&gt;
&lt;em&gt;Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.&lt;/em&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fNabidka.aspx%2523skoleni"&gt;Podrobné
informace o kurzu a možnost přihlásit se na kurz&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fSkoleni-UML-OOP-Navrhove-vzory-1.aspx"&gt;Program
kurzu&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.renestein.net%2fOhlasy-Ucastniku-Na-Kurzy.aspx"&gt;Výběr
z ohlasů na kurzy&lt;/a&gt;
&lt;br&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2frenestein.net%2fCasto-Kladene-Dotazy-Kurzy-FAQ.aspx"&gt;FAQ
- často kladené dotazy ke kurzům&lt;/a&gt; 
&lt;hr&gt;
&lt;p&gt;
&lt;b&gt;Veřejný kurz Základy objektově orientovaného návrhu a vývoje (UML 0)&lt;/b&gt; 
&lt;p&gt;
Datum konání kurzu: &lt;b&gt;14. - 16. 1. 2013&lt;/b&gt; 
&lt;p&gt;
Místo konání&lt;strong&gt;:&lt;/strong&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.tutor.cz%2f"&gt;Školící
středisko Tutor&lt;/a&gt; 
&lt;p&gt;
U Půjčovny 2&lt;br&gt;
110 00 Praha 1 
&lt;p&gt;
&lt;em&gt;Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.&lt;/em&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2frenestein.net%2fNabidka.aspx%23skoleniOOP0"&gt;Podrobné
informace o kurzu a možnost přihlásit se na kurz&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2frenestein.net%2fSkoleni-Zaklady-Objektove-Orientovaneho-Navrhu-UML-0.aspx"&gt;Program
kurzu&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.renestein.net%2fOhlasy-Ucastniku-Na-Kurzy.aspx"&gt;Výběr
z ohlasů na kurzy&lt;/a&gt;
&lt;br&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2frenestein.net%2fCasto-Kladene-Dotazy-Kurzy-FAQ.aspx"&gt;FAQ&amp;nbsp;
- často kladené dotazy ke kurzům&lt;/a&gt; 
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;b&gt;Veřejný kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních
aplikací 2&lt;/b&gt; 
&lt;p&gt;
Datum konání kurzu:&amp;nbsp; &lt;strong&gt;21. - 23. 1. 2013&lt;/strong&gt; 
&lt;p&gt;
Místo konání&lt;strong&gt;:&lt;/strong&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.tutor.cz%2f"&gt;Školící
středisko Tutor&lt;/a&gt; 
&lt;p&gt;
U Půjčovny 2&lt;br&gt;
110 00 Praha 1 
&lt;p&gt;
&lt;em&gt;Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.&lt;/em&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.renestein.net%2fNabidka.aspx%23SkoleniOOP2"&gt;Podrobné
informace o kurzu a možnost přihlásit se na kurz&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.renestein.net%2fSkoleni-Navrhove-vzory-2.aspx"&gt;Program
kurzu&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.renestein.net%2fOhlasy-Ucastniku-Na-Kurzy.aspx"&gt;Výběr
z ohlasů na kurzy&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2frenestein.net%2fCasto-Kladene-Dotazy-Kurzy-FAQ.aspx"&gt;FAQ
- často kladené dotazy ke kurzům&lt;/a&gt; 
&lt;p&gt;
Těším se na shledání na kurzu.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=dac3a930-3326-4521-a8b1-7e84ae709519" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,dac3a930-3326-4521-a8b1-7e84ae709519.aspx</comments>
      <category>Analytické drobky</category>
      <category>Kurzy UML a OOP</category>
      <category>Návrhové vzory</category>
      <category>Ostatní</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=b193e5d5-a047-4196-a8e4-11b97b380b19</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,b193e5d5-a047-4196-a8e4-11b97b380b19.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,b193e5d5-a047-4196-a8e4-11b97b380b19.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=b193e5d5-a047-4196-a8e4-11b97b380b19</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Opět bych vás chtěl pozvat na kurz Objektovými principy a návrhovými vzory řízený
design a vývoj kvalitních aplikací 1.
</p>
        <hr />
        <p>
          <b>Veřejný kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních
aplikací 1</b>
        </p>
        <p>
Datum konání kurzu:  <strong><strong><abbr>
4. 6.
</abbr>
– 
<abbr>
6. 6. 2012
</abbr></strong></strong></p>
        <p>
          <strong>
            <strong>
              <abbr>
              </abbr>
            </strong>
          </strong>Místo konání<strong>:</strong></p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fwww.tutor.cz%2f">Školící
středisko Tutor</a>
        </p>
        <p>
U Půjčovny 2<br />
110 00 Praha 1 
</p>
        <p>
          <em>Po celý den máme k dispozici wifi připojení a samozřejmě také teplé i studené
nápoje. V ceně kurzu jsou obědy v restauraci.</em>
        </p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fNabidka.aspx%2523skoleni">Podrobné
informace o kurzu a možnost přihlásit se na kurz</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fSkoleni-UML-OOP-Navrhove-vzory-1.aspx">Program
kurzu</a>
          <br />
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fOhlasy-Ucastniku-Na-Kurzy.aspx">Výběr
z ohlasů na kurz</a>
        </p>
        <p>
Zde jsou ještě některé ohlasy z twitteru na  kurzy, které proběhly na podzim
roku 2011:<br /><a href="https://twitter.com/#!/AugiCZ/status/129271721512538112">https://twitter.com/#!/AugiCZ/status/129271721512538112</a></p>
        <p>
          <a href="https://twitter.com/#!/topascz/status/129228333991989248">https://twitter.com/#!/topascz/status/129228333991989248</a>
          <br />
          <br />
          <a href="https://twitter.com/#!/petrkucera/statuses/129474672575250432">https://twitter.com/#!/petrkucera/statuses/129474672575250432</a>
        </p>
        <p>
          <br />
          <a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;url=http%3a%2f%2frenestein.net%2fCasto-Kladene-Dotazy-Kurzy-FAQ.aspx">FAQ
- často kladené dotazy ke kurzům</a>
        </p>
        <p>
          <hr />
        </p>
        <p>
Tento rok se na jaře uskuteční pouze výše popsaný kurz. Dva další kurzy, <a href="http://www.renestein.net/Nabidka.aspx#skoleniOOP0">Školení
Základy objektově orientovaného návrhu a vývoje (UML 0)</a> a <a href="http://www.renestein.net/Nabidka.aspx#SkoleniOOP2">Pokročilé
návrhové vzory a objektové principy 2</a>, proběhnou na podzim a můžete se na ně také 
předběžně hlásit. Důvodem, proč tyto kurzy neproběhnou na jaře, je moje vytížení dalšími
projekty.
</p>
        <p>
Pro jistotu připomenu, že všechny kurzy lze také objednávat v “inhouse” variantě,
kdy kurz proběhne ve vaší firmě v termínech, na kterých se spolu domluvíme, a za podmínek,
které s vámi ráda dohodne <a href="mailto:petra@renestein.net" target="_blank">Petra
Steinová</a>. V inhouse variantě je také samozřejmě možné zcela upravit program kurzu 
a věnovat se jen “specialitkám” a “špekům”, které v aplikaci řešíte.
</p>
        <p>
Budu se těšit na záludné dotazy na kurzu.<img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Pozvnka-na-kurz-objektovch-princip-a-nvr_7F57/wlEmoticon-smile_2.png" /></p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=b193e5d5-a047-4196-a8e4-11b97b380b19" />
      </body>
      <title>Pozv&amp;aacute;nka na kurz objektov&amp;yacute;ch principů a n&amp;aacute;vrhov&amp;yacute;ch vzorů &amp;ndash; jaro 2012 a informace k dal&amp;scaron;&amp;iacute;m kurzům</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,b193e5d5-a047-4196-a8e4-11b97b380b19.aspx</guid>
      <link>http://blog.renestein.net/Pozvaacutenka+Na+Kurz+Objektovyacutech+Princip%c5%af+A+Naacutevrhovyacutech+Vzor%c5%af+Ndash+Jaro+2012+A+Informace+K+Dalscaroniacutem+Kurz%c5%afm.aspx</link>
      <pubDate>Tue, 20 Mar 2012 08:28:04 GMT</pubDate>
      <description>&lt;p&gt;
Opět bych vás chtěl pozvat na kurz Objektovými principy a návrhovými vzory řízený
design a vývoj kvalitních aplikací 1.
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;b&gt;Veřejný kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních
aplikací 1&lt;/b&gt; 
&lt;p&gt;
Datum konání kurzu:&amp;nbsp; &lt;strong&gt;&lt;strong&gt;
&lt;abbr&gt;
4. 6.
&lt;/abbr&gt;
– 
&lt;abbr&gt;
6. 6. 2012
&lt;/abbr&gt;
&lt;/strong&gt;&lt;/strong&gt; 
&lt;p&gt;
&lt;strong&gt;&lt;strong&gt;
&lt;abbr&gt;
&lt;/abbr&gt;
&lt;/strong&gt;&lt;/strong&gt;Místo konání&lt;strong&gt;:&lt;/strong&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fwww.tutor.cz%2f"&gt;Školící
středisko Tutor&lt;/a&gt; 
&lt;p&gt;
U Půjčovny 2&lt;br&gt;
110 00 Praha 1 
&lt;p&gt;
&lt;em&gt;Po celý den máme k dispozici wifi připojení a samozřejmě také teplé i studené
nápoje. V ceně kurzu jsou obědy v restauraci.&lt;/em&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fNabidka.aspx%2523skoleni"&gt;Podrobné
informace o kurzu a možnost přihlásit se na kurz&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fSkoleni-UML-OOP-Navrhove-vzory-1.aspx"&gt;Program
kurzu&lt;/a&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2fblog.renestein.net%2fct.ashx%3fid%3dd6fd9894-f5cd-4d7d-9e78-53974f98d52d%26url%3dhttp%253a%252f%252fwww.renestein.net%252fOhlasy-Ucastniku-Na-Kurzy.aspx"&gt;Výběr
z ohlasů na kurz&lt;/a&gt; 
&lt;p&gt;
Zde jsou ještě některé ohlasy z twitteru na&amp;nbsp; kurzy, které proběhly na podzim
roku 2011:&lt;br&gt;
&lt;a href="https://twitter.com/#!/AugiCZ/status/129271721512538112"&gt;https://twitter.com/#!/AugiCZ/status/129271721512538112&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://twitter.com/#!/topascz/status/129228333991989248"&gt;https://twitter.com/#!/topascz/status/129228333991989248&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="https://twitter.com/#!/petrkucera/statuses/129474672575250432"&gt;https://twitter.com/#!/petrkucera/statuses/129474672575250432&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a&amp;amp;url=http%3a%2f%2frenestein.net%2fCasto-Kladene-Dotazy-Kurzy-FAQ.aspx"&gt;FAQ
- často kladené dotazy ke kurzům&lt;/a&gt; 
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
Tento rok se na jaře uskuteční pouze výše popsaný kurz. Dva další kurzy, &lt;a href="http://www.renestein.net/Nabidka.aspx#skoleniOOP0"&gt;Školení
Základy objektově orientovaného návrhu a vývoje (UML 0)&lt;/a&gt; a &lt;a href="http://www.renestein.net/Nabidka.aspx#SkoleniOOP2"&gt;Pokročilé
návrhové vzory a objektové principy 2&lt;/a&gt;, proběhnou na podzim a můžete se na ně také&amp;nbsp;
předběžně hlásit. Důvodem, proč tyto kurzy neproběhnou na jaře, je moje vytížení dalšími
projekty.
&lt;/p&gt;
&lt;p&gt;
Pro jistotu připomenu, že všechny kurzy lze také objednávat v “inhouse” variantě,
kdy kurz proběhne ve vaší firmě v termínech, na kterých se spolu domluvíme, a za podmínek,
které s vámi ráda dohodne &lt;a href="mailto:petra@renestein.net" target="_blank"&gt;Petra
Steinová&lt;/a&gt;. V inhouse variantě je také samozřejmě možné zcela upravit program kurzu&amp;nbsp;
a věnovat se jen “specialitkám” a “špekům”, které v aplikaci řešíte.
&lt;/p&gt;
&lt;p&gt;
Budu se těšit na záludné dotazy na kurzu.&lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Pozvnka-na-kurz-objektovch-princip-a-nvr_7F57/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=b193e5d5-a047-4196-a8e4-11b97b380b19" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,b193e5d5-a047-4196-a8e4-11b97b380b19.aspx</comments>
      <category>Kurzy UML a OOP</category>
      <category>Návrhové vzory</category>
      <category>UML</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=b5f8610e-3243-4c83-b55f-a5f50f883aad</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,b5f8610e-3243-4c83-b55f-a5f50f883aad.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,b5f8610e-3243-4c83-b55f-a5f50f883aad.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=b5f8610e-3243-4c83-b55f-a5f50f883aad</wfw:commentRss>
      <slash:comments>11</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
 
</p>
        <p>
Jestliže používáte i přes <a href="http://blog.renestein.net/Entity+Framework+43+Code+First+Nechutnyacute+Probleacutem+S+TPC+Mapovaacuteniacutem.aspx">jeho
nezralost</a> Entity Framework, nebo jste si zvolili jiné ORM, které zvládá “lazy
loading”, neboli zpožděné, či chcete-li dodatečné nahrání dat do typových kolekcí,
možná jste přemýšleli, jak byste stejnou  službu napsali ve starší aplikaci,
která žádné ORM nepoužívá, nebo v hybridní aplikaci, pod kterou si představuju aplikaci,
jejíž starší moduly ORM nepoužívají, ale novější moduly již s přístupem přes ORM počítají.
I bez ORM byste ale často v aplikaci rádi využívali některé vychytávky, které s sebou
přináší ORM. Dnes chci ukázat, že zpožděné nahrávání kolekcí není žádná magie, která
by bez ORM byla v aplikaci zapovězena. Když budete mít zájem, můžeme v dalších článcích
probrat například i automatickou detekci změn vlastností na objektech a s tím související
ukládání objektů i odvolávání proběhlých změn, jestliže zákazník nechce změny uložit
a třeba na formuláři stiskne po deseti minutách zuřivé editace objektu a po několika
masivních business transakcích, které pozmění desítky objektů najednou, tlačítko Storno.
</p>
        <p>
Co si představit pod zpožděným nahráním  objektů v kolekci? Můžeme vyjít z již
zlidovělé třídy Objednávka (Order), která má kolekci svých položek (kolekce Items).
Místo nahrání všech položek objednávky z databáze ihned po vytvoření instance objednávky,
odložíme nahrání položek až na dobu, kdy budou v aplikaci poprvé potřeba. Před klienty
třídy Order ale tuto optimalizaci skrýváme tak, že kolekci Items naplníme položkami
teprve při prvním přístupu ke kolekci přes veřejné rozhraní třídy Order.
</p>
        <script src="https://gist.github.com/2020641.js">
        </script>
        <p>
Jde sice o triviální kód, kdy v get akcesoru kontrolujeme bool příznak m_itemsIsLoaded
(byly položky nahrány?) a při prvním přístupu ke kolekci zavoláme metodu loadItems,
ale představte si, že tento kód u starší aplikace zběsile doplňujete ke každé kolekci
v každé třídě, kde teď stojíte o zpožděné nahrávání. Čitelnost kódu je citelně snížena
a chrabří obhájci principu jedné odpovědnosti třídy (SRP) právě dopisují Kladivo na
heretiky <a href="http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)">S.O.L.I.D</a>ní
víry pravé a připravují v zájmu lepší veřejné vývojářské morálky autodafé účtu dotyčného
vývojáře na všech významných sociálních sítích.
</p>
        <p>
Můžeme se rozhodnout, že nebudeme zatěžovat zpožděným nahráváním kolekcí přímo třídu
Objednávka, ale že vytvoříme proxy třídu, do které odpovědnost za tuto “infrastrukturní
službu” vložíme. Proxy objekt je, jak známo, objekt, který má z hlediska klienta stejné
rozhraní jako původní objekt a klient si není vědom, že pracuje s instancí zástupce
(surogátem) třídy Order, a ne s originální třídou Order. 
</p>
        <p>
Samotná třída Objednávka není nijak zatěžována znalostí, že její kolekce Items je
nahrána až při prvním přístupu ke kolekci. Zpožděné nahrávání zvládne ale potomek
třídy Order, třída OrderProxy, ve které je podobný kód, který se původně nacházel
v objednávce. A protože platí, že potomek nějaké třídy může být v aplikaci používán
na všech místech, kde je očekáván předek, můžeme například z repozitáře/identitní
mapy objektů začít ihned vydávat klientům instance OrderProxy místo originální třídy
Order.
</p>
        <script src="https://gist.github.com/2020775.js">
        </script>
        <p>
Odpovědnosti už jsme rozdělili lépe, protože třída Order není zatěžována zpožděným
nahráváním kolekce a jediným důvodem existence třídy OrderProxy je právě zpožděné
nahrávání. Přesto stále platí, že budeme do úmoru psát další a další třídy Proxy,
u nichž  jediná kreativní vývojářská činnost spočívá v pojmenování bool proměnné,
která nám sděluje, jestli kolekce byla, nebo nebyla nahrána. Je možné si práci zjednodušit
tím, že například vytvoříme T4 šablonu, která proxy třídy vygeneruje, ale my se dnes
zaměříme na to, jak vytvořit proxy třídu, aniž bychom museli psát proxy ručně nebo
spoléhat na T4 šablony.<br /><br />
Použijeme takzvanou dynamickou proxy, kterou si lze představit jako nástroj, kterému
řekneme, co má proxy dělat, a on pro každou třídu bez ohledu na unikátní rozhraní
každé třídy sám vygeneruje proxy, která pro tuto třídu implementuje námi vyžadované
chování. Slovo “dynamická” u proxy vyjadřuje hlavně to, že jde o proxy generovanou
automaticky za běhu aplikace! V našem konkrétním scénáři se zpožděným nahráváním objektů
vytvoříme i pro aplikaci, která má v business vrstvě stovky i  tisíce tříd jen
jednu další třídu, která představuje “deskriptor” pro každou proxy zajišťující 
zpožděné nahrávání kolekcí, přičemž platí, že tento “deskriptor“  bude schopen
obsloužit všechny kolekce ve všech třídách. Sice se pro každou třídu vytvoří unikátní
proxy (potomek originální třídy), ale tato proxy se bude odkazovat na obecný scénář
zpožděného nahrávání v našem “deskriptoru”. Při čtení dalších částí článku mějte na
paměti, že kód dělá stále to samé, jako námi vytvořená třída OrderProxy výše, jen
jsme kód zobecnili tak, abychom si dokázali vynutit zpožděné nahrávání kolekcí ve
všech třídách. Vedlejším a nepříjemným důsledkem tohoto zobecnění, jak je tomu asi
u každé abstrakce,  je samozřejmě snížená schopnost jen po letmém prolétnutí
infrastrukturního kódu očima poznat, oč přesně usilujeme. Výhodou však bude to, že
náš deskriptor oddálí zmiňované autodafé vývojáře už jen tím, že dodržuje princip <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY-Don't
repeat yourself</a> – místo psaní jen mírně obměněného kódu v každé konkrétní proxy
jednorázově vyjádříme náš záměr zpožděně nahrávat kolekce v “deskriptoru” pro generování
dynamické proxy.
</p>
        <p>
Mějme třídy Customer, Order a OrderItem. Zajímá nás hlavně to, že třída Customer má
kolekci objednávek a třída Order kolekci položek objednávky. Pro všechny kolekce chceme
doplnit zpožděné nahrání kolekcí.<br />
Všimněte si také toho, že vlastnosti s kolekcemi jsou virtuální. Stále platí, že dynamická
proxy je potomkem naší třídy a musí být schopna přepsat implementaci a doplnit kód
pro zpožděné nahrání kolekce stejně, jako jsme přepisovali get akcesor u “manuální”
proxy výše.
</p>
        <script src="https://gist.github.com/2020853.js">
        </script>
        <p>
I když je mnohem zábavnější napsat si podporu pro dynamicky generované proxy sám,
ne vždy bychom měli vynalézat na projektu kolo, zvláště když jsme v časovém presu 
a navíc pod drábovou knutou nudných projektových manažerů surově lámajících naše vývojářská
křídla <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/1b979a3deb47_7BE6/wlEmoticon-smile_2.png" /> ,
a alespoň v tomto článku použijeme výborný a ověřený nástroj pro generování dynamických
proxy z <a href="http://www.castleproject.org/">projektu Castle</a>. Nejjednodušší
způsob přidání knihovny pro generování dynamických proxy spočívá v instalaci přes <a href="http://nuget.codeplex.com/">NuGet</a>.
V Powershell konzoli ve Visual studiu zadejte příkaz.
</p>
        <script src="https://gist.github.com/2020893.js">
        </script>
        <p>
Vytvoření dynamické proxy v Castlu je kupodivu otázkou napsání  jednoho řádku
kódu. My služby Castlu zapouzdříme do naší vlastní třídy ProxyEngine. 
</p>
        <script src="https://gist.github.com/2020959.js">
        </script>
        <p>
Do konstruktoru třídy ProxyEngine dostáváme instanci třídy SimpleObjectFactory, kterou
si můžete prozatím zjednodušeně představit jako velmi jednoduchou generickou továrnu
na výrobu business objektů, která zároveň funguje jako identitní mapa. Její kompletní
výpis naleznete níže v tomto článku.
</p>
        <p>
Hlavní je pro nás metoda AddDefaultProxy, která dostává jako první argument typ, pro
který má být vytvořena proxy. Tedy předáte-li typový deskriptor objednávky, metoda
by měla vyrobit OrderProxy. Druhým argumentem jsou argumenty, které mají být předány
konstruktoru naší třídy. Jestliže objednávka vyžaduje v konstruktoru odkaz na své
id, vygenerovaná proxy třída garantuje, že jí id bude do konstruktoru předáno.
</p>
        <p>
Teď přichází zajímavá část – vytvoření proxy: 
</p>
        <script src="https://gist.github.com/2020977.js">
        </script>
        <p>
Proměnná <em>m_proxyGenerator </em>je instancí třídy <em>ProxyEngine </em>z Castlu,
která představuje výkonné jádro pro generování proxy. Prvním argumentem metody proxyGenerator.CreateClassProxy
je typ, pro který chceme proxy vytvořit. Druhý argument typu ProxyGenerationOptions
jsou různé volby, které dovolují jemně řídit, jak se bude vytvořená proxy chovat.
My zatím potřebujeme jen sdělit, které metody originální (ne proxy) třídy chceme v
proxy “přepsat”. Proto jsou ProxyGenerationOptions inicializovány hned v konstruktoru
třídy ProxyEngine a je jim předána instance třídy ProxyGenerationHook, která, jak
ihned ve výpise uvidíme, vybírá kolekce, u kterých má být podporováno zpožděné nahrání
objektů.
</p>
        <script src="https://gist.github.com/2021032.js">
        </script>
        <p>
Rozhraní IProxyGenerationHook je rozhraní Castlu. Metoda ShouldInterceptMethod z tohoto
rozhraní je metoda, kterou Castle používá k rozhodnutí, jaké metody a vlastnosti mají
být “přepsány” v dynamické proxy. Třída ProxyGenerationHook v metodě ShouldInterceptMethod
říká  - tedy vrací true - , že chceme zachytit všechny get akcesory <em>( methodInfo.IsSpecialName&amp;&amp;
methodInfo.Name.StartsWith(GET_METHOD_NAME_PREFIX</em>), jejichž návratovou hodnotou
je kolekce. Přesněji řečeno každá kolekce podporující generické rozhraní ICollection&lt;T&gt;
(methodInfo.ReturnType.GetInterface(COLLECTION_NAME) != null). Jiných metod ani vlastností
si v tomto článku u tříd  nevšímáme, a proto pro ně z metody ShouldInterceptMethod
vrátíme false. Zajímavou metodou v rozhraní IProxyGenerationHook je i metoda NonVirtualMemberNotification,
pomocí níž nás Castle informuje, že v originální třídě je nevirtuální metoda – my
metodu NonVirtualMemberNotification nevyužíváme, ale mohli bychom do ní snadno doplnit
kód, který vyhodí výjimku, jestliže jste Castlem notifikováni, že existuje nevirtuální
vlastnost vracející ICollection&lt;T&gt;, protože vaše firemní konvence vyžadují,
aby všechny kolekce podporovaly zpožděné nahrávání kolekce.<br /><br />
Nyní jsme již Castlu sdělili, že máme zájem “přepsat” get akcesory kolekcí, ale stále
Castle neví,  jakou logiku má do těchto get akcesorů doplnit. Vraťme se k metodě
CreateClassProxy. Třetí argument je zřejmý, předáváme argumenty, se kterými má být
zavolán konstruktor naší originální třídy. Posledním argumentem metody CreateClassProxy
je objekt, který nás zajímá nejvíce – jedná se o tzv. interceptora, který bude použit
vždy, když je na proxy použita  metoda/vlastnost, kterou chceme “přepsat”. Stále
píšeme obecné řešení zpožděného nahrávání kolekcí, a proto metodě CreateClassProxy
předáme interceptora s výmluvným názvem LazyLoadInterceptor. LazyLoadInterceptor je
ten “zázračný” typ, který jsem výše popisoval jako obecný deskriptor funkcí, které
musí podporovat dynamická proxy pro instanci z každé třídy v business vrstvě.
</p>
        <p>
Náš <em>LazyLoadInterceptor</em>, stejně jako každý jiný interceptor, musí podporovat
rozhraní  <em>IInterceptor</em> z Castlu. Rozhraní <em>IInterceptor </em>má jedinou
metodu Intercept, kterou Castle zavolá vždy, když je volána metoda/vlastnost, kterou
chceme “přepsat”.
</p>
        <script src="https://gist.github.com/2021104.js">
        </script>
        <p>
Metodě Intercept je předán objekt Invocation, který nese základní informace o volané
metodě.Kromě dalších vlastností je vhodné si zapamatovat, že v invocation.Method naleznete
objekt MethodInfo  (deskriptor metody) a  v InvocationTarget zase konkrétní
instanci, na které je metoda volána<em>. <strong>Zdůrazním, že touto konkrétní instancí
je v našem případě (dynamický) proxy objekt, ne instance originální třídy.</strong></em></p>
        <p>
          <strong>Zkusme si scénář v metodě Intercept projít. Mějme na paměti, že i když ten
kód může vypadat na první pohled děsivě, neřeší nic jiného než ručně napsaná proxy
výše. Zkusme se v našem popisu pro názornost zaměřit na konkrétní proxy objektu reprezentujícího
zákazníka Josefa Nováka v momentě, kdy je poprvé přistoupeno k jeho kolekci Orders
(seznam objednávek), i když kód v <em>LazyLoadInterceptoru </em>funguje analogicky
ve všech dalších proxy business tříd v systému.</strong>
        </p>
        <ul>
          <li>
Metoda <em>Intercept </em>nejprve na předaném objektu <em>invocation </em>volá metodu <em>Proceed</em>. 
Metoda Proceed vyvolá get akcesor originálního objektu a návratovou hodnotu (při prvním
volání prázdnou typovou kolekci objednávek) nalezneme ve vlastnosti invocation.ReturnValue.
Proč voláme nejprve invocation.Proceed? Protože potřebujeme v interceptoru kolekci,
do které u zákazníka můžeme nahrát objednávky, a tuto kolekci stále spravuje instance
originální třídy, jak si můžete ověřit ve výpisu třídy Customer.<br /></li>
          <li>
Jestliže se nejedná o první volání metody, nic neděláme, protože kolekce už musí být
naplněna. V proměnné m_inspectedMethods máme názvy vlastností, které jsme již u daného
objektu zpracovali.<br /></li>
          <li>
Jestliže invocation.ReturnValue je null, opět nic dalšího neděláme. Nemáme žádnou
kolekci, do které bychom mohli nahrát objednávky. 
<br /></li>
          <li>
Do kolekce m_inspectedMethods přidáme název aktuální vlastnosti (Orders), protože
jsme ji již začali zpracovávat.<br /><em>m_inspectedMethods.Add(invocation.Method.Name);<br /><br /></em></li>
          <li>
Nejprve potřebujeme zjistit, z jaké třídy pocházejí objekty,  které budeme do
kolekce, jejíž data nahráváme, přidávat. U objektu zákazník a kolekce Orders půjde
samozřejmě o objekty z třídy Objednávka.<br /><em>Type collectionItemType = invocation.Method.ReturnType.GetInterface(COLLECTION_INTERFACE_NAME).GetGenericArguments()[0];<br /></em></li>
          <li>
Dohledáme třídu z databázové vrstvy, která nám bude schopna vrátit seznam objednávek
pro daného zákazníka.<br /><em>Object dbComponent = findDbComponent(collectionItemType);<br /></em>Pro účely článku je zvolena jednoduchá jmenná konvence -  rozhraní pro přístup
k databázi se jmenují vždy I&lt;Název třídy&gt;DbComponent. Pro objednávku tedy hledáme
typ IOrderDbComponent. Pokud db komponentu nenalezneme, nic dalšího nemůžeme dělat.<br /></li>
          <li>
V nalezené db komponentě musíme najít metodu, která nám vrátí záznamy pro všechny
objednávky zákazníka Josefa Nováka.  
<br /><em>MethodInfo methodInfo = getDbCollectionMethodInfo(dbComponent, invocation.TargetType,
collectionItemType);<br /></em>Opět je zvolená jmenná konvence, kdy metoda má tvar Get{TypeInCollection}RecordsBy{ParentType}Id"
a přijímá jeden argument typu int . V našem scénáři hledáme tedy na db komponentě
metodu GetOrderRecordsByCustomerId, která přijímá id “rodičovského” zákazníka. <em>V
dalších článcích bych rád ukázal, jak se bez této i dalších dále zmíněných jmenných
konvence obejdeme a budeme moci nakonfigurovat zpožděné nahrávání kolekcí přes jakkoli
nazvané třídy a metody.<br /></em>Stejně jako v předchozím bodě platí, že nenalezneme-li vyhovující metodu, nic
dalšího nemůžeme dělat.<br /></li>
          <li>
            <em>
            </em>Dále u objektu zákazník získáme hodnotu vlastnosti Id, kterou potřebujeme
pro vyvolání metody na db komponentě nalezené v předchozím odstavci<br /><em>  int? objectId = getTargetObjectId(invocation.InvocationTarget);<br /></em></li>
          <li>
Zavoláme metodu GetOrderRecordsByCustomerId. Návratovou hodnotou je objekt DataTable,
který v našem scénáři obsahuje záznamy všech objednávek patřících Josefu Novákovi.<br /><em>DataTable retValues = methodInfo.Invoke(dbComponent, new object[] {objectId})
as DataTable;<br /></em></li>
          <li>
Přes pomocnou třídu SimpleObjectFactory, kterou LazyLoadInterceptor vyžaduje v konstruktoru,
vytvoříme <strong>proxy </strong>objekty Objednávek a přidáme je do kolekce Orders
zákazníka.<br /><em>var targetCollection = invocation.ReturnValue;<br />
addItemsToCollection(targetCollection, collectionItemType, retValues, invocation);<br /></em>Navíc se u každé vytvořené objednávky pokusíme nastavit odkaz na  “rodičovského
zákazníka”, přesněji řečeno na <strong>proxy </strong>zákazníka. Opět je zvolena jmenná
konvence, kdy objekt Order musí obsahovat vlastnost nazvanou Customer, jinak k nastavení
“rodiče” nejde. Jak jsem již psal výše, v dalších článcích bychom si měli ukázat,
jak tyto výchozí jmenné konvence rozšíříme a dovolíme i jejich úplné nahrazení.<br /></li>
          <li>
Hotovo, kolekce Orders u zákazníka Josefa Nováka je naplněna proxy objekty třídy Order
a stejný scénář proběhne i při přístupu ke kolekci Items (položky objednávky) u každé
objednávky.</li>
        </ul>
        <p>
Nyní můžeme vyzkoušet, jestli jsou proxy třídy generovány a hlavně jestli naše úsilí
nebylo marné a proxy třídy podporují zpožděné nahrávání kolekce.
</p>
        <script src="https://gist.github.com/2021321.js">
        </script>
        <p>
 
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/1b979a3deb47_7BE6/consoleProxy_4.png">
            <img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="consoleProxy" border="0" alt="consoleProxy" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/1b979a3deb47_7BE6/consoleProxy_thumb_1.png" width="644" height="322" />
          </a>
        </p>
        <p>
Výsledkem by měl být tento výpis, ze kterého je patrné :<br /></p>
        <ul>
          <li>
Místo originální třídy jsou používány proxy třídy. 
</li>
          <li>
Kolekce jsou naplněny, i když ve třídách Customer ani Order žádný kód pro nahrání
kolekce nemáme. 
</li>
          <li>
Je naplněna kolekce Orders u zákazníka i kolekce Items u každé objednávky.</li>
        </ul>
        <p>
Následuje slibovaný výpis generické třídy SimpleObjectFactory.  
</p>
        <p>
Třída SimpleObjectFactory podporuje rozhraní SimpleObjectFactory a při vydání objektu:
</p>
        <ol>
          <li>
Funguje jako identitní mapa, takže každý objekt je nahrán jen jednou (nyní per process,
což se dá snadno změnit).<br /></li>
          <li>
Používá záměrně služby “zastaralé” db vrstvy pro nahrání dat každého objektu – vytváření
objektů ale deleguje na ProxyEngine.<br /></li>
          <li>
Pokusí se nastavit hodnoty jednoduchých vlastností u vytvořených proxy objektů – jestliže
se název vlastnosti shoduje s názvem sloupce v datovém zdroji, je vlastnost objektu
nastavena na hodnotu sloupečku, která je uložena v řádku  vytaženém z databáze.</li>
        </ol>
        <script src="https://gist.github.com/2021356.js">
        </script>
        <p>
Co můžeme udělat dále v dalších článcích, jestliže budete mít zájem:
</p>
        <ol>
          <li>
Nebudeme spoléhat na jmenné konvence při plnění kolekci a “rodičovských” vlastností,
ale dovolíme nakonfigurovat interceptora tak, abychom mohli spravovat asociace mezi
třídami podle konvencí unikátních pro každý projekt, a přitom abychom nemuseli do
těchto nízkoúrovňových proxy služeb moc zasahovat. Konfiguraci provedeme nejlépe pomocí
fluentního API.<br /></li>
          <li>
LazyLoadInterceptor nebude používat stále dokola reflexi pro dohledání typů a metod,
ale bude nalezené hodnoty cachovat.<br /></li>
          <li>
            <em>Budeme schopni podpořit i zpožděné nahrávání “rodičovských” vlastností. Prozatím
je “rodičovská” vlastnost nastavena jen při nahrání kolekce – když vytáhnete z databáze
jako první objednávku a sáhnete na její vlastnost Customer, vlastnost vám nyní vrátí
null!<br /></em>
          </li>
          <li>
Mohli bychom rozšířit proxy třídy o sledování změn vlastností a umožnit u každého
objektu uložení změn nebo vrácení změn (undo).<br /></li>
          <li>
Zavedeme repozitáře (Repository), které i v hybridní aplikaci sjednotí ve vyšších
vrstvách aplikace přístup k objektům, které jsou nahrány přes ORM i k objektům vytaženým
z našich stávajících “old school” db/business služeb.<br /></li>
          <li>
Místo toho, abychom generovali dynamické proxy vždy po startu aplikace, umoříme jednorázově
(pro většinu aplikací stejně zanedbatelnou) režii spojenou s tímto postupem vygenerováním
a uložením assembly s dynamickými proxy při prvním spuštění nové verze aplikace. Při
dalším spuštění aplikace se již použijí proxy ve vygenerované assembly.</li>
        </ol>
        <p>
Pro dnešek toho bylo ale myslím dost. Snad jen dodám, že jsem se v tomto článku chtěl
vyhnout různým buzzwordům, ale fajnšmekrům potvrdím, co asi sami tuší, že jsme v tomto
článku zavítali do hájemství <a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">AOP
- aspektově orientovaného programování</a>.
</p>
        <p>
Celý projekt si <a href="https://bitbucket.org/renestein/rstein.misc/src">můžete stáhnout</a>,
nejlépe přes Mercurial (hg). Součástí zdrojových kódů je i jednoduchá třída napodobující
rozhraní tradičních “db komponent” pro přístup do databáze a zpřístupňující data v
Datasetu. 
</p>
        <script src="https://gist.github.com/2021422.js">
        </script>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=b5f8610e-3243-4c83-b55f-a5f50f883aad" />
      </body>
      <title>Lazy loading (zpožděn&amp;eacute; nahr&amp;aacute;v&amp;aacute;n&amp;iacute;) objektů do kolekce i ve star&amp;scaron;&amp;iacute; aplikaci s využit&amp;iacute;m dynamick&amp;eacute; proxy</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,b5f8610e-3243-4c83-b55f-a5f50f883aad.aspx</guid>
      <link>http://blog.renestein.net/Lazy+Loading+Zpo%c5%bed%c4%9bneacute+Nahraacutevaacuteniacute+Objekt%c5%af+Do+Kolekce+I+Ve+Starscaroniacute+Aplikaci+S+Vyu%c5%beitiacutem+Dynamickeacute+Proxy.aspx</link>
      <pubDate>Mon, 12 Mar 2012 13:06:49 GMT</pubDate>
      <description>&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Jestliže používáte i přes &lt;a href="http://blog.renestein.net/Entity+Framework+43+Code+First+Nechutnyacute+Probleacutem+S+TPC+Mapovaacuteniacutem.aspx"&gt;jeho
nezralost&lt;/a&gt; Entity Framework, nebo jste si zvolili jiné ORM, které zvládá “lazy
loading”, neboli zpožděné, či chcete-li dodatečné nahrání dat do typových kolekcí,
možná jste přemýšleli, jak byste stejnou&amp;nbsp; službu napsali ve starší aplikaci,
která žádné ORM nepoužívá, nebo v hybridní aplikaci, pod kterou si představuju aplikaci,
jejíž starší moduly ORM nepoužívají, ale novější moduly již s přístupem přes ORM počítají.
I bez ORM byste ale často v aplikaci rádi využívali některé vychytávky, které s sebou
přináší ORM. Dnes chci ukázat, že zpožděné nahrávání kolekcí není žádná magie, která
by bez ORM byla v aplikaci zapovězena. Když budete mít zájem, můžeme v dalších článcích
probrat například i automatickou detekci změn vlastností na objektech a s tím související
ukládání objektů i odvolávání proběhlých změn, jestliže zákazník nechce změny uložit
a třeba na formuláři stiskne po deseti minutách zuřivé editace objektu a po několika
masivních business transakcích, které pozmění desítky objektů najednou, tlačítko Storno.
&lt;/p&gt;
&lt;p&gt;
Co si představit pod zpožděným nahráním&amp;nbsp; objektů v kolekci? Můžeme vyjít z již
zlidovělé třídy Objednávka (Order), která má kolekci svých položek (kolekce Items).
Místo nahrání všech položek objednávky z databáze ihned po vytvoření instance objednávky,
odložíme nahrání položek až na dobu, kdy budou v aplikaci poprvé potřeba. Před klienty
třídy Order ale tuto optimalizaci skrýváme tak, že kolekci Items naplníme položkami
teprve při prvním přístupu ke kolekci přes veřejné rozhraní třídy Order.
&lt;/p&gt;
&lt;script src="https://gist.github.com/2020641.js"&gt; &lt;/script&gt;
&lt;p&gt;
Jde sice o triviální kód, kdy v get akcesoru kontrolujeme bool příznak m_itemsIsLoaded
(byly položky nahrány?) a při prvním přístupu ke kolekci zavoláme metodu loadItems,
ale představte si, že tento kód u starší aplikace zběsile doplňujete ke každé kolekci
v každé třídě, kde teď stojíte o zpožděné nahrávání. Čitelnost kódu je citelně snížena
a chrabří obhájci principu jedné odpovědnosti třídy (SRP) právě dopisují Kladivo na
heretiky &lt;a href="http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)"&gt;S.O.L.I.D&lt;/a&gt;ní
víry pravé a připravují v zájmu lepší veřejné vývojářské morálky autodafé účtu dotyčného
vývojáře na všech významných sociálních sítích.
&lt;/p&gt;
&lt;p&gt;
Můžeme se rozhodnout, že nebudeme zatěžovat zpožděným nahráváním kolekcí přímo třídu
Objednávka, ale že vytvoříme proxy třídu, do které odpovědnost za tuto “infrastrukturní
službu” vložíme. Proxy objekt je, jak známo, objekt, který má z hlediska klienta stejné
rozhraní jako původní objekt a klient si není vědom, že pracuje s instancí zástupce
(surogátem) třídy Order, a ne s originální třídou Order. 
&lt;/p&gt;
&lt;p&gt;
Samotná třída Objednávka není nijak zatěžována znalostí, že její kolekce Items je
nahrána až při prvním přístupu ke kolekci. Zpožděné nahrávání zvládne ale potomek
třídy Order, třída OrderProxy, ve které je podobný kód, který se původně nacházel
v objednávce. A protože platí, že potomek nějaké třídy může být v aplikaci používán
na všech místech, kde je očekáván předek, můžeme například z repozitáře/identitní
mapy objektů začít ihned vydávat klientům instance OrderProxy místo originální třídy
Order.
&lt;/p&gt;
&lt;script src="https://gist.github.com/2020775.js"&gt; &lt;/script&gt;
&lt;p&gt;
Odpovědnosti už jsme rozdělili lépe, protože třída Order není zatěžována zpožděným
nahráváním kolekce a jediným důvodem existence třídy OrderProxy je právě zpožděné
nahrávání. Přesto stále platí, že budeme do úmoru psát další a další třídy Proxy,
u nichž&amp;nbsp; jediná kreativní vývojářská činnost spočívá v pojmenování bool proměnné,
která nám sděluje, jestli kolekce byla, nebo nebyla nahrána. Je možné si práci zjednodušit
tím, že například vytvoříme T4 šablonu, která proxy třídy vygeneruje, ale my se dnes
zaměříme na to, jak vytvořit proxy třídu, aniž bychom museli psát proxy ručně nebo
spoléhat na T4 šablony.&lt;br&gt;
&lt;br&gt;
Použijeme takzvanou dynamickou proxy, kterou si lze představit jako nástroj, kterému
řekneme, co má proxy dělat, a on pro každou třídu bez ohledu na unikátní rozhraní
každé třídy sám vygeneruje proxy, která pro tuto třídu implementuje námi vyžadované
chování. Slovo “dynamická” u proxy vyjadřuje hlavně to, že jde o proxy generovanou
automaticky za běhu aplikace! V našem konkrétním scénáři se zpožděným nahráváním objektů
vytvoříme i pro aplikaci, která má v business vrstvě stovky i&amp;nbsp; tisíce tříd jen
jednu další třídu, která představuje “deskriptor” pro každou proxy zajišťující&amp;nbsp;
zpožděné nahrávání kolekcí, přičemž platí, že tento “deskriptor“&amp;nbsp; bude schopen
obsloužit všechny kolekce ve všech třídách. Sice se pro každou třídu vytvoří unikátní
proxy (potomek originální třídy), ale tato proxy se bude odkazovat na obecný scénář
zpožděného nahrávání v našem “deskriptoru”. Při čtení dalších částí článku mějte na
paměti, že kód dělá stále to samé, jako námi vytvořená třída OrderProxy výše, jen
jsme kód zobecnili tak, abychom si dokázali vynutit zpožděné nahrávání kolekcí ve
všech třídách. Vedlejším a nepříjemným důsledkem tohoto zobecnění, jak je tomu asi
u každé abstrakce,&amp;nbsp; je samozřejmě snížená schopnost jen po letmém prolétnutí
infrastrukturního kódu očima poznat, oč přesně usilujeme. Výhodou však bude to, že
náš deskriptor oddálí zmiňované autodafé vývojáře už jen tím, že dodržuje princip &lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself"&gt;DRY-Don't
repeat yourself&lt;/a&gt; – místo psaní jen mírně obměněného kódu v každé konkrétní proxy
jednorázově vyjádříme náš záměr zpožděně nahrávat kolekce v “deskriptoru” pro generování
dynamické proxy.
&lt;/p&gt;
&lt;p&gt;
Mějme třídy Customer, Order a OrderItem. Zajímá nás hlavně to, že třída Customer má
kolekci objednávek a třída Order kolekci položek objednávky. Pro všechny kolekce chceme
doplnit zpožděné nahrání kolekcí.&lt;br&gt;
Všimněte si také toho, že vlastnosti s kolekcemi jsou virtuální. Stále platí, že dynamická
proxy je potomkem naší třídy a musí být schopna přepsat implementaci a doplnit kód
pro zpožděné nahrání kolekce stejně, jako jsme přepisovali get akcesor u “manuální”
proxy výše.
&lt;/p&gt;
&lt;script src="https://gist.github.com/2020853.js"&gt; &lt;/script&gt;
&lt;p&gt;
I když je mnohem zábavnější napsat si podporu pro dynamicky generované proxy sám,
ne vždy bychom měli vynalézat na projektu kolo, zvláště když jsme v časovém presu&amp;nbsp;
a navíc pod drábovou knutou nudných projektových manažerů surově lámajících naše vývojářská
křídla &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/1b979a3deb47_7BE6/wlEmoticon-smile_2.png"&gt; ,
a alespoň v tomto článku použijeme výborný a ověřený nástroj pro generování dynamických
proxy z &lt;a href="http://www.castleproject.org/"&gt;projektu Castle&lt;/a&gt;. Nejjednodušší
způsob přidání knihovny pro generování dynamických proxy spočívá v instalaci přes &lt;a href="http://nuget.codeplex.com/"&gt;NuGet&lt;/a&gt;.
V Powershell konzoli ve Visual studiu zadejte příkaz.
&lt;/p&gt;
&lt;script src="https://gist.github.com/2020893.js"&gt; &lt;/script&gt;
&lt;p&gt;
Vytvoření dynamické proxy v Castlu je kupodivu otázkou napsání&amp;nbsp; jednoho řádku
kódu. My služby Castlu zapouzdříme do naší vlastní třídy ProxyEngine. 
&lt;/p&gt;
&lt;script src="https://gist.github.com/2020959.js"&gt; &lt;/script&gt;
&lt;p&gt;
Do konstruktoru třídy ProxyEngine dostáváme instanci třídy SimpleObjectFactory, kterou
si můžete prozatím zjednodušeně představit jako velmi jednoduchou generickou továrnu
na výrobu business objektů, která zároveň funguje jako identitní mapa. Její kompletní
výpis naleznete níže v tomto článku.
&lt;/p&gt;
&lt;p&gt;
Hlavní je pro nás metoda AddDefaultProxy, která dostává jako první argument typ, pro
který má být vytvořena proxy. Tedy předáte-li typový deskriptor objednávky, metoda
by měla vyrobit OrderProxy. Druhým argumentem jsou argumenty, které mají být předány
konstruktoru naší třídy. Jestliže objednávka vyžaduje v konstruktoru odkaz na své
id, vygenerovaná proxy třída garantuje, že jí id bude do konstruktoru předáno.
&lt;/p&gt;
&lt;p&gt;
Teď přichází zajímavá část – vytvoření proxy: 
&lt;/p&gt;
&lt;script src="https://gist.github.com/2020977.js"&gt; &lt;/script&gt;
&lt;p&gt;
Proměnná &lt;em&gt;m_proxyGenerator &lt;/em&gt;je instancí třídy &lt;em&gt;ProxyEngine &lt;/em&gt;z Castlu,
která představuje výkonné jádro pro generování proxy. Prvním argumentem metody proxyGenerator.CreateClassProxy
je typ, pro který chceme proxy vytvořit. Druhý argument typu ProxyGenerationOptions
jsou různé volby, které dovolují jemně řídit, jak se bude vytvořená proxy chovat.
My zatím potřebujeme jen sdělit, které metody originální (ne proxy) třídy chceme v
proxy “přepsat”. Proto jsou ProxyGenerationOptions inicializovány hned v konstruktoru
třídy ProxyEngine a je jim předána instance třídy ProxyGenerationHook, která, jak
ihned ve výpise uvidíme, vybírá kolekce, u kterých má být podporováno zpožděné nahrání
objektů.
&lt;/p&gt;
&lt;script src="https://gist.github.com/2021032.js"&gt; &lt;/script&gt;
&lt;p&gt;
Rozhraní IProxyGenerationHook je rozhraní Castlu. Metoda ShouldInterceptMethod z tohoto
rozhraní je metoda, kterou Castle používá k rozhodnutí, jaké metody a vlastnosti mají
být “přepsány” v dynamické proxy. Třída ProxyGenerationHook v metodě ShouldInterceptMethod
říká&amp;nbsp; - tedy vrací true - , že chceme zachytit všechny get akcesory &lt;em&gt;( methodInfo.IsSpecialName&amp;amp;&amp;amp;
methodInfo.Name.StartsWith(GET_METHOD_NAME_PREFIX&lt;/em&gt;), jejichž návratovou hodnotou
je kolekce. Přesněji řečeno každá kolekce podporující generické rozhraní ICollection&amp;lt;T&amp;gt;
(methodInfo.ReturnType.GetInterface(COLLECTION_NAME) != null). Jiných metod ani vlastností
si v tomto článku u tříd&amp;nbsp; nevšímáme, a proto pro ně z metody ShouldInterceptMethod
vrátíme false. Zajímavou metodou v rozhraní IProxyGenerationHook je i metoda NonVirtualMemberNotification,
pomocí níž nás Castle informuje, že v originální třídě je nevirtuální metoda – my
metodu NonVirtualMemberNotification nevyužíváme, ale mohli bychom do ní snadno doplnit
kód, který vyhodí výjimku, jestliže jste Castlem notifikováni, že existuje nevirtuální
vlastnost vracející ICollection&amp;lt;T&amp;gt;, protože vaše firemní konvence vyžadují,
aby všechny kolekce podporovaly zpožděné nahrávání kolekce.&lt;br&gt;
&lt;br&gt;
Nyní jsme již Castlu sdělili, že máme zájem “přepsat” get akcesory kolekcí, ale stále
Castle neví,&amp;nbsp; jakou logiku má do těchto get akcesorů doplnit. Vraťme se k metodě
CreateClassProxy. Třetí argument je zřejmý, předáváme argumenty, se kterými má být
zavolán konstruktor naší originální třídy. Posledním argumentem metody CreateClassProxy
je objekt, který nás zajímá nejvíce – jedná se o tzv. interceptora, který bude použit
vždy, když je na proxy použita&amp;nbsp; metoda/vlastnost, kterou chceme “přepsat”. Stále
píšeme obecné řešení zpožděného nahrávání kolekcí, a proto metodě CreateClassProxy
předáme interceptora s výmluvným názvem LazyLoadInterceptor. LazyLoadInterceptor je
ten “zázračný” typ, který jsem výše popisoval jako obecný deskriptor funkcí, které
musí podporovat dynamická proxy pro instanci z každé třídy v business vrstvě.
&lt;/p&gt;
&lt;p&gt;
Náš &lt;em&gt;LazyLoadInterceptor&lt;/em&gt;, stejně jako každý jiný interceptor, musí podporovat
rozhraní&amp;nbsp; &lt;em&gt;IInterceptor&lt;/em&gt; z Castlu. Rozhraní &lt;em&gt;IInterceptor &lt;/em&gt;má jedinou
metodu Intercept, kterou Castle zavolá vždy, když je volána metoda/vlastnost, kterou
chceme “přepsat”.
&lt;/p&gt;
&lt;script src="https://gist.github.com/2021104.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metodě Intercept je předán objekt Invocation, který nese základní informace o volané
metodě.Kromě dalších vlastností je vhodné si zapamatovat, že v invocation.Method naleznete
objekt MethodInfo&amp;nbsp; (deskriptor metody) a&amp;nbsp; v InvocationTarget zase konkrétní
instanci, na které je metoda volána&lt;em&gt;. &lt;strong&gt;Zdůrazním, že touto konkrétní instancí
je v našem případě (dynamický) proxy objekt, ne instance originální třídy.&lt;/strong&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Zkusme si scénář v metodě Intercept projít. Mějme na paměti, že i když ten
kód může vypadat na první pohled děsivě, neřeší nic jiného než ručně napsaná proxy
výše. Zkusme se v našem popisu pro názornost zaměřit na konkrétní proxy objektu reprezentujícího
zákazníka Josefa Nováka v momentě, kdy je poprvé přistoupeno k jeho kolekci Orders
(seznam objednávek), i když kód v &lt;em&gt;LazyLoadInterceptoru &lt;/em&gt;funguje analogicky
ve všech dalších proxy business tříd v systému.&lt;/strong&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Metoda &lt;em&gt;Intercept &lt;/em&gt;nejprve na předaném objektu &lt;em&gt;invocation &lt;/em&gt;volá metodu &lt;em&gt;Proceed&lt;/em&gt;.&amp;nbsp;
Metoda Proceed vyvolá get akcesor originálního objektu a návratovou hodnotu (při prvním
volání prázdnou typovou kolekci objednávek) nalezneme ve vlastnosti invocation.ReturnValue.
Proč voláme nejprve invocation.Proceed? Protože potřebujeme v interceptoru kolekci,
do které u zákazníka můžeme nahrát objednávky, a tuto kolekci stále spravuje instance
originální třídy, jak si můžete ověřit ve výpisu třídy Customer.&lt;br&gt;
&lt;li&gt;
Jestliže se nejedná o první volání metody, nic neděláme, protože kolekce už musí být
naplněna. V proměnné m_inspectedMethods máme názvy vlastností, které jsme již u daného
objektu zpracovali.&lt;br&gt;
&lt;li&gt;
Jestliže invocation.ReturnValue je null, opět nic dalšího neděláme. Nemáme žádnou
kolekci, do které bychom mohli nahrát objednávky. 
&lt;br&gt;
&lt;li&gt;
Do kolekce m_inspectedMethods přidáme název aktuální vlastnosti (Orders), protože
jsme ji již začali zpracovávat.&lt;br&gt;
&lt;em&gt;m_inspectedMethods.Add(invocation.Method.Name);&lt;br&gt;
&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
Nejprve potřebujeme zjistit, z jaké třídy pocházejí objekty,&amp;nbsp; které budeme do
kolekce, jejíž data nahráváme, přidávat. U objektu zákazník a kolekce Orders půjde
samozřejmě o objekty z třídy Objednávka.&lt;br&gt;
&lt;em&gt;Type collectionItemType = invocation.Method.ReturnType.GetInterface(COLLECTION_INTERFACE_NAME).GetGenericArguments()[0];&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
Dohledáme třídu z databázové vrstvy, která nám bude schopna vrátit seznam objednávek
pro daného zákazníka.&lt;br&gt;
&lt;em&gt;Object dbComponent = findDbComponent(collectionItemType);&lt;br&gt;
&lt;/em&gt;Pro účely článku je zvolena jednoduchá jmenná konvence -&amp;nbsp; rozhraní pro přístup
k databázi se jmenují vždy I&amp;lt;Název třídy&amp;gt;DbComponent. Pro objednávku tedy hledáme
typ IOrderDbComponent. Pokud db komponentu nenalezneme, nic dalšího nemůžeme dělat.&lt;br&gt;
&lt;li&gt;
V nalezené db komponentě musíme najít metodu, která nám vrátí záznamy pro všechny
objednávky zákazníka Josefa Nováka.&amp;nbsp; 
&lt;br&gt;
&lt;em&gt;MethodInfo methodInfo = getDbCollectionMethodInfo(dbComponent, invocation.TargetType,
collectionItemType);&lt;br&gt;
&lt;/em&gt;Opět je zvolená jmenná konvence, kdy metoda má tvar Get{TypeInCollection}RecordsBy{ParentType}Id"
a přijímá jeden argument typu int . V našem scénáři hledáme tedy na db komponentě
metodu GetOrderRecordsByCustomerId, která přijímá id “rodičovského” zákazníka. &lt;em&gt;V
dalších článcích bych rád ukázal, jak se bez této i dalších dále zmíněných jmenných
konvence obejdeme a budeme moci nakonfigurovat zpožděné nahrávání kolekcí přes jakkoli
nazvané třídy a metody.&lt;br&gt;
&lt;/em&gt;Stejně jako v předchozím bodě platí, že nenalezneme-li vyhovující metodu, nic
dalšího nemůžeme dělat.&lt;br&gt;
&lt;li&gt;
&lt;em&gt;&lt;/em&gt;Dále u objektu zákazník získáme hodnotu vlastnosti Id, kterou potřebujeme
pro vyvolání metody na db komponentě nalezené v předchozím odstavci&lt;br&gt;
&lt;em&gt;&amp;nbsp; int? objectId = getTargetObjectId(invocation.InvocationTarget);&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
Zavoláme metodu GetOrderRecordsByCustomerId. Návratovou hodnotou je objekt DataTable,
který v našem scénáři obsahuje záznamy všech objednávek patřících Josefu Novákovi.&lt;br&gt;
&lt;em&gt;DataTable retValues = methodInfo.Invoke(dbComponent, new object[] {objectId})
as DataTable;&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
Přes pomocnou třídu SimpleObjectFactory, kterou LazyLoadInterceptor vyžaduje v konstruktoru,
vytvoříme &lt;strong&gt;proxy &lt;/strong&gt;objekty Objednávek a přidáme je do kolekce Orders
zákazníka.&lt;br&gt;
&lt;em&gt;var targetCollection = invocation.ReturnValue;&lt;br&gt;
addItemsToCollection(targetCollection, collectionItemType, retValues, invocation);&lt;br&gt;
&lt;/em&gt;Navíc se u každé vytvořené objednávky pokusíme nastavit odkaz na&amp;nbsp; “rodičovského
zákazníka”, přesněji řečeno na &lt;strong&gt;proxy &lt;/strong&gt;zákazníka. Opět je zvolena jmenná
konvence, kdy objekt Order musí obsahovat vlastnost nazvanou Customer, jinak k nastavení
“rodiče” nejde. Jak jsem již psal výše, v dalších článcích bychom si měli ukázat,
jak tyto výchozí jmenné konvence rozšíříme a dovolíme i jejich úplné nahrazení.&lt;br&gt;
&lt;li&gt;
Hotovo, kolekce Orders u zákazníka Josefa Nováka je naplněna proxy objekty třídy Order
a stejný scénář proběhne i při přístupu ke kolekci Items (položky objednávky) u každé
objednávky.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Nyní můžeme vyzkoušet, jestli jsou proxy třídy generovány a hlavně jestli naše úsilí
nebylo marné a proxy třídy podporují zpožděné nahrávání kolekce.
&lt;/p&gt;
&lt;script src="https://gist.github.com/2021321.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/1b979a3deb47_7BE6/consoleProxy_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="consoleProxy" border="0" alt="consoleProxy" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/1b979a3deb47_7BE6/consoleProxy_thumb_1.png" width="644" height="322"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Výsledkem by měl být tento výpis, ze kterého je patrné :&lt;br&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Místo originální třídy jsou používány proxy třídy. 
&lt;li&gt;
Kolekce jsou naplněny, i když ve třídách Customer ani Order žádný kód pro nahrání
kolekce nemáme. 
&lt;li&gt;
Je naplněna kolekce Orders u zákazníka i kolekce Items u každé objednávky.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Následuje slibovaný výpis generické třídy SimpleObjectFactory.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Třída SimpleObjectFactory podporuje rozhraní SimpleObjectFactory a při vydání objektu:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Funguje jako identitní mapa, takže každý objekt je nahrán jen jednou (nyní per process,
což se dá snadno změnit).&lt;br&gt;
&lt;li&gt;
Používá záměrně služby “zastaralé” db vrstvy pro nahrání dat každého objektu – vytváření
objektů ale deleguje na ProxyEngine.&lt;br&gt;
&lt;li&gt;
Pokusí se nastavit hodnoty jednoduchých vlastností u vytvořených proxy objektů – jestliže
se název vlastnosti shoduje s názvem sloupce v datovém zdroji, je vlastnost objektu
nastavena na hodnotu sloupečku, která je uložena v řádku&amp;nbsp; vytaženém z databáze.&lt;/li&gt;
&lt;/ol&gt;
&lt;script src="https://gist.github.com/2021356.js"&gt; &lt;/script&gt;
&lt;p&gt;
Co můžeme udělat dále v dalších článcích, jestliže budete mít zájem:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Nebudeme spoléhat na jmenné konvence při plnění kolekci a “rodičovských” vlastností,
ale dovolíme nakonfigurovat interceptora tak, abychom mohli spravovat asociace mezi
třídami podle konvencí unikátních pro každý projekt, a přitom abychom nemuseli do
těchto nízkoúrovňových proxy služeb moc zasahovat. Konfiguraci provedeme nejlépe pomocí
fluentního API.&lt;br&gt;
&lt;li&gt;
LazyLoadInterceptor nebude používat stále dokola reflexi pro dohledání typů a metod,
ale bude nalezené hodnoty cachovat.&lt;br&gt;
&lt;li&gt;
&lt;em&gt;Budeme schopni podpořit i zpožděné nahrávání “rodičovských” vlastností. Prozatím
je “rodičovská” vlastnost nastavena jen při nahrání kolekce – když vytáhnete z databáze
jako první objednávku a sáhnete na její vlastnost Customer, vlastnost vám nyní vrátí
null!&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
Mohli bychom rozšířit proxy třídy o sledování změn vlastností a umožnit u každého
objektu uložení změn nebo vrácení změn (undo).&lt;br&gt;
&lt;li&gt;
Zavedeme repozitáře (Repository), které i v hybridní aplikaci sjednotí ve vyšších
vrstvách aplikace přístup k objektům, které jsou nahrány přes ORM i k objektům vytaženým
z našich stávajících “old school” db/business služeb.&lt;br&gt;
&lt;li&gt;
Místo toho, abychom generovali dynamické proxy vždy po startu aplikace, umoříme jednorázově
(pro většinu aplikací stejně zanedbatelnou) režii spojenou s tímto postupem vygenerováním
a uložením assembly s dynamickými proxy při prvním spuštění nové verze aplikace. Při
dalším spuštění aplikace se již použijí proxy ve vygenerované assembly.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Pro dnešek toho bylo ale myslím dost. Snad jen dodám, že jsem se v tomto článku chtěl
vyhnout různým buzzwordům, ale fajnšmekrům potvrdím, co asi sami tuší, že jsme v tomto
článku zavítali do hájemství &lt;a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming"&gt;AOP
- aspektově orientovaného programování&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Celý projekt si &lt;a href="https://bitbucket.org/renestein/rstein.misc/src"&gt;můžete stáhnout&lt;/a&gt;,
nejlépe přes Mercurial (hg). Součástí zdrojových kódů je i jednoduchá třída napodobující
rozhraní tradičních “db komponent” pro přístup do databáze a zpřístupňující data v
Datasetu. 
&lt;/p&gt;
&lt;script src="https://gist.github.com/2021422.js"&gt; &lt;/script&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=b5f8610e-3243-4c83-b55f-a5f50f883aad" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,b5f8610e-3243-4c83-b55f-a5f50f883aad.aspx</comments>
      <category>.NET Framework</category>
      <category>Entity Framework</category>
      <category>Návrhové vzory</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=5773e213-e568-429b-85da-179c954f22c3</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,5773e213-e568-429b-85da-179c954f22c3.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,5773e213-e568-429b-85da-179c954f22c3.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=5773e213-e568-429b-85da-179c954f22c3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Několik lidí mi psalo na email, že by chtěli demo z <a href="http://jdem.cz/suru9">první
přednášky</a> na <a href="http://ms-fest.cz/">MS Festu</a>.
</p>
        <p>
Zde je:
</p>
        <p>
          <a href="http://jdem.cz/sxs63">
            <big>http://jdem.cz/sxs63</big>
          </a>
        </p>
        <p>
Podrobné informace, na které nebyl na přednášce čas, naleznete v sérii článků <strong>Tipy
pro Windows Phone 7 aplikace</strong> v <a href="http://jdem.cz/sxs92">sekci o WP7
aplikacích</a>. 
</p>
        <p>
          <em>Asi nemusím zdůrazňovat, že jde o demo, tedy kód nemusí mít produkční kvalitu,
za nic neručím a určitě ke kódu není poskytována žádná podpora.<img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Demo-z-MS-Festu_D343/wlEmoticon-smile_2.png" /></em>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=5773e213-e568-429b-85da-179c954f22c3" />
      </body>
      <title>Demo z MS Festu</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,5773e213-e568-429b-85da-179c954f22c3.aspx</guid>
      <link>http://blog.renestein.net/Demo+Z+MS+Festu.aspx</link>
      <pubDate>Tue, 06 Dec 2011 14:17:03 GMT</pubDate>
      <description>&lt;p&gt;
Několik lidí mi psalo na email, že by chtěli demo z &lt;a href="http://jdem.cz/suru9"&gt;první
přednášky&lt;/a&gt; na &lt;a href="http://ms-fest.cz/"&gt;MS Festu&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Zde je:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://jdem.cz/sxs63"&gt;&lt;big&gt;http://jdem.cz/sxs63&lt;/big&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Podrobné informace, na které nebyl na přednášce čas, naleznete v sérii článků &lt;strong&gt;Tipy
pro Windows Phone 7 aplikace&lt;/strong&gt; v &lt;a href="http://jdem.cz/sxs92"&gt;sekci o WP7
aplikacích&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Asi nemusím zdůrazňovat, že jde o demo, tedy kód nemusí mít produkční kvalitu,
za nic neručím a určitě ke kódu není poskytována žádná podpora.&lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Demo-z-MS-Festu_D343/wlEmoticon-smile_2.png"&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=5773e213-e568-429b-85da-179c954f22c3" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,5773e213-e568-429b-85da-179c954f22c3.aspx</comments>
      <category>C#</category>
      <category>Návrhové vzory</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=c5624a7e-98ca-44a7-94c9-8f5824a19f85</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,c5624a7e-98ca-44a7-94c9-8f5824a19f85.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,c5624a7e-98ca-44a7-94c9-8f5824a19f85.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=c5624a7e-98ca-44a7-94c9-8f5824a19f85</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://blog.renestein.net/Pozvaacutenka+Na+Kurzy+Objektovyacutech+Princip%C5%AF+A+Naacutevrhovyacutech+Vzor%C5%AF+Ndash+Podzim+2011.aspx">Pozvánka
na mé kurzy</a> na blogu trochu zapadla, a protože tento týden dvě firmy zvolily raději
inhouse variantu kurzu, a tím se uvolnila místa na veřejných kurzech, i když předtím
jsme museli na začátku srpna některé zájemce o veřejné kurzy OOP 0 a OOP 1 odmítat,
dávám i pro další zájemce znovu <a href="http://blog.renestein.net/Pozvaacutenka+Na+Kurzy+Objektovyacutech+Princip%C5%AF+A+Naacutevrhovyacutech+Vzor%C5%AF+Ndash+Podzim+2011.aspx">odkaz
na pozvánku</a>.
</p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=c5624a7e-98ca-44a7-94c9-8f5824a19f85" />
      </body>
      <title>Připomenut&amp;iacute;: Kurzy &amp;ndash; podzim 2011</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,c5624a7e-98ca-44a7-94c9-8f5824a19f85.aspx</guid>
      <link>http://blog.renestein.net/P%c5%99ipomenutiacute+Kurzy+Ndash+Podzim+2011.aspx</link>
      <pubDate>Tue, 30 Aug 2011 10:48:54 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://blog.renestein.net/Pozvaacutenka+Na+Kurzy+Objektovyacutech+Princip%C5%AF+A+Naacutevrhovyacutech+Vzor%C5%AF+Ndash+Podzim+2011.aspx"&gt;Pozvánka
na mé kurzy&lt;/a&gt; na blogu trochu zapadla, a protože tento týden dvě firmy zvolily raději
inhouse variantu kurzu, a tím se uvolnila místa na veřejných kurzech, i když předtím
jsme museli na začátku srpna některé zájemce o veřejné kurzy OOP 0 a OOP 1 odmítat,
dávám i pro další zájemce znovu &lt;a href="http://blog.renestein.net/Pozvaacutenka+Na+Kurzy+Objektovyacutech+Princip%C5%AF+A+Naacutevrhovyacutech+Vzor%C5%AF+Ndash+Podzim+2011.aspx"&gt;odkaz
na pozvánku&lt;/a&gt;.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=c5624a7e-98ca-44a7-94c9-8f5824a19f85" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,c5624a7e-98ca-44a7-94c9-8f5824a19f85.aspx</comments>
      <category>Analytické drobky</category>
      <category>Kurzy UML a OOP</category>
      <category>Návrhové vzory</category>
      <category>UML</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=59132463-8265-453d-b94a-d44bc3a07878</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,59132463-8265-453d-b94a-d44bc3a07878.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,59132463-8265-453d-b94a-d44bc3a07878.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=59132463-8265-453d-b94a-d44bc3a07878</wfw:commentRss>
      <slash:comments>19</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
 
</p>
        <p>
Dnes na twitteru <a href="http://twitter.com/#!/DavidGrudl/status/77398502971424768">David
Grudl odkázal</a> na debatu, která se <a href="http://php.vrana.cz/prace-s-vlastnostmi-pomoci-metod.php#d-11965">týká
vlastností v PHP</a>. O vlastnostech v PHP mluvit nechci, ale v tomto  příspěvku
se chci dotknout některých “dogmat”, které se ozývají stále častěji a které byly použity
jako univerzální kladivo na oponenty  i v odkazované diskuzi.
</p>
        <p>
Jedno zvláštní dogma se týká principu jedné odpovědnosti třídy (Single responsibility
principle). Tento princip říká, že třída by měla mít jednu přesně vymezenou odpovědnost,
která je v souladu s jejím názvem. I když na první přečtění se tento princip zdá neproblematický,
dá se zneužít jako univerzální kladivo. <strong>Dogmatici mi říkali, že jedna odpovědnost
si vynucuje, aby třída vždy měla právě jednu metodu, která tuto odpovědnost realizuje. </strong>Není
nad přehledný svět objektových dogmatiků, kde objekt je jen stupidní kontajner na
jednu (de facto globální?) funkci.<img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Opakovn-zklad_119C2/wlEmoticon-smile_2.png" /></p>
        <p>
Dogmatiky tohoto zvláštního ražení  zanedbejme jako ztracené případy a SRP obohaťme
o další vysvětlení, které říká, že třída by měla mít jen jeden důvod ke změně. Tento
princip je užitečný v tom, se snaží z aplikací odstranit všemocné božské (God) objekty,
které mnohdy už svým názvem signalizují, že řeší spoustu věcí. UniversalOrderAndInvoiceProcessor
oznamuje, že se bude měnit nejen, když se změní zpracování objednávek, ale také když
se změní zpracování faktur. Jednoduché, což? Proč o tomhle jednoduchém principu vůbec
dále mluvit?
</p>
        <p>
V diskuzi se o SRP <a href="http://php.vrana.cz/prace-s-vlastnostmi-pomoci-metod.php#d-11965">mluví
(viz i příspěvky níže</a>), ale diskutující tam ve  své argumentaci používají
něco, čemu na kurzech u SRP říkám falešné alternativy.
</p>
        <p>
Mějme stejně jako v diskusi svou třídu Image, která nese informace o obrázku. Obrázek
chceme uložit.
</p>
        <p>
Varianta 1, kdy obrázek nese informace a současně nabízí metodu Save, ve které uloží
data do souboru.
</p>
        <script src="https://gist.github.com/1009256.js">
        </script>
        <p>
Co je v diskuzi vyčítáno této třídě? Porušuje princip jedné odpovědnosti, protože
podle některých (Jiří Knesl, Ondřej Mirteš)  řeší dvě věci najednou – <strong>nese
data o obrázku a současně data ukládá. </strong>Souhlasím, že jde o porušení SRP,
ale hlavním důvodem je to, že metoda Save je napsána tak,  že třídu Image ukládáme <strong>vždy </strong>do
souboru. Co když budeme chtít třídu Image uložit do nějakého “response” streamu na
webovém serveru, nebo uložit přímo do databáze? Tuto třídu skutečně budeme měnit ze
dvou důvodů – jednou, když přidáme nebo odebereme informace o obrázku a také, když
budeme chtít ukládat obrázek do databáze, musíme rozšířit stávající metodu Save, což
povede k tomu, že metoda bude mít v sobě nějaký podivný switch a  bude trpět
smíšenou odpovědností, protože bude dělat několik věcí najednou,  nebo můžeme
přidat novou samostatnou metodu SaveToDb. 
</p>
        <p>
Jedinou (!?) alternativou v diskuzi k tomuto postupu je vyvedení odpovědnosti za ukládání
do různých úložišť do samostatných objektů, které mohou být  skryty za jednotným
rozhraním.
</p>
        <script src="https://gist.github.com/1009269.js">
        </script>
        <p>
Toto řešení důsledně separuje odpovědnosti, navíc je velmi snadné přidat další implementaci
rozhraní IImagePersistor, např. DbPersistor, který data uloží do databáze. Už v diskuzi
Jakub Vrána ale upozorňuje na to, že se mu nelíbí, jak se řešení komplikuje pro uživatele-vývojáře,
který s třídami bude pracovat, protože tento vývojář musí vědět, že existuje nějaký
IImagePersistor/FilePersistor odpovědný za uložení dat. Třída Image nestačí k tomu,
abyste dokázali vygenerovat data obrázku a uložit je, což může být ve vaší knihovně
častý scénář. Také bych rád poprvé v tomto článku připomněl princip OOP, ke kterému
se za chvíli vrátím, že <strong>objekt představuje jednotu svého stavu a chování,
které je pro tento stav definováno. </strong></p>
        <p>
          <strong>Psal jsem o falešných alternativách, můžeme najít i jiná řešení. Co ponechat
metodu Save ve třídě Image, ale z třídy Image udělat tzv kompozitor - objekt, který
skládá své chování tak, že využívá další pomocné objekty, na kterých závisí, a nabízí
intuitivní rozhraní pro klienty. </strong>
        </p>
        <script src="https://gist.github.com/1009274.js">
        </script>
        <p>
Odpovědnosti jsou stále separovány a dokonce třída Image, náš kompozitor, dodržuje
pravidlo, které říká, že kompozitor by měl být jednodušší než suma funkcí jeho pomocných
objektů.  Klient třídy Image nemusí pracovat přímo s třídou FilePersistor, a
přitom nemáme kód pro ukládání do souboru přímo ve třídě Image. Problém je, že metoda
Save třídy Image vždy vytváří FilePersistor. Klient třídy Image si nemůže vyžádat
to námi dříve zmiňované ukládání obrázku do databáze, a navíc třída Image závisí na
jedné konkrétní třídě FilePersistor, u níž přímo volá konstruktor. <strong>V třídě
Image mixujeme vytváření grafu spolupracujících objektů se samotným použitím pomocných
objektů. Opět jde o dvě odpovědnosti, které bychom měli oddělit – SRP, nezapomeňme.</strong></p>
        <p>
Nejprve ale zkusme vyřešit problém s tím, že klient nemůže ukládat data do databáze,
protože třída Image ukládá data vždy do souboru.
</p>
        <script src="https://gist.github.com/1009285.js">
        </script>
        <p>
Jednoduše přidáme další variantu metody, která přijímá odkaz na IImagePersistor, v
našem případě třeba na DbPersistor. Původní metoda Save bez argumentů řeší ukládání
do souboru. Ukládání do souboru je nejčastější scénář, který je zvolen jako výchozí.
Stále ale tady máme problém s tím, že v metodě Save konstruujeme "natvrdo" FilePersistor.
A navíc naše API klientům trochu lže. V podtextu klientovi sděluje, že výchozí metoda
Save nemá žádné další závislosti, i když z implementace, !a jen z implementace!, 
je zřejmé, že jsme závislí na přítomnosti třídy FilePersistor. <em>Poznámka: V C#
4 můžeme použít volitelné argumenty u jedné metody, ale na principu této varianty
řešení se moc nemění.</em></p>
        <p>
Zkusme naše prozatím ulhané API vylepšit a dodržet SRP.  Oddělme nyní konstrukci
pomocných objektů, na kterých závisíme, od jejich použití v metodě Save. 
</p>
        <script src="https://gist.github.com/1009297.js">
        </script>
        <p>
Objekt Image si nyní v konstruktoru vynucuje předání IIMagePersitoru. Když klient
IImagePersistor nepředá, objekt nezvznikne – sám konstruktor garantuje, že buď objekt
Image má vyplněny všechny závislosti, nebo vůbec nevznikne. Vytvořili jsme konstruktor,
který může použít a automaticky naplnit DI kontajner, nebo různé abstraktní továrny
registrované v DI kontajneru  apod. <strong>DI kontajner je přesně tím objektem,
který by měl být v aplikaci odpovědný za konstrukci grafu objektů,</strong> v metodě
Save objektu Image injektovaný IImagePersistor jen používáme. SRP v praxi.
</p>
        <p>
Možný že ale v tomto případě je injektování závislostí přes konstruktor moc striktní.
Co když nám skutečně vyhovuje, že můžeme bez DI kontajneru vytvořit objekt Image,
který bude data ukládat do souboru. Pak můžeme využít injektování přes vlastnosti,
kdy příslušnou vlastnost po vzniku objektu vyplníme rozumnou výchozí hodnotou – v
našem případě instancí FilePersistoru. Poté ale platí, že třídu Image stále částečně
zatěžujete konstrukcí objektů…<br />
U většiny DI kontajnerů je preferováno injektování závislostí přes konstruktory, všechny,
které znám,  si ale poradí ale i s injektováním závislostí přes vlastností a
u <a href="http://www.google.cz/search?hl=cs&amp;source=hp&amp;q=MEF+MSDN&amp;aq=f&amp;aqi=&amp;aql=&amp;oq=">MEF</a>u
bych řekl, že injektování závislostí pomocí vlastností hrají prim.
</p>
        <script src="https://gist.github.com/1009315.js">
        </script>
        <p>
Všechny tyto varianty mají své výhody a nevýhody a asi nemusím zdůrazňovat, že ani
jedna není univerzálním kladivem. Varianty s injektováním závislostí (konstruktor,
metoda, vlastnost) jsou samozřejmě mnohem lépe testovatelné.
</p>
        <p>
Dokážu přidat i další příklady, ale chtěl jsem,  abyste viděli, že SRP není ani
nesmysl, ale ani princip, který by, podobně jako to zaznělo v diskuzi, sděloval –
existují jen dvě alternativy, jak rozdělovat odpovědnosti, a ZROVNA TA TVOJE JE ŠPATNĚ.
</p>
        <p>
A poslední  poznámka:
</p>
        <p>
Jiřé Knesl také v diskuzi uvedl: “ objekt buďto data reprezentuje (pak má settery/gettery),
nebo vykonává činnost (pak dostane data parametry)”. Tohle je podle mě  postoj
blízký hlavně některým Javistům, o čemž svědčí i podle mého soudu schematický a nevěrohodný <a href="http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html">článek,
který se zabývá vlastnostmi v Javě</a> a na který se J. Knesl odkazuje. Znovu připomínám,
že <strong>objekt představuje jednotu svého stavu a chování, které je pro tento stav
definováno.  </strong>Objekt, který má jen gettery a settery, je ”krabičkou na
data”, pouhou strukturou známou i z neobjektových jazyků, a když má objekt jen metody,
tak jde o (v mnoha případech skutečně globální) funkce/procedury, které prefixujeme
názvem proměnné/třídy. V diskuzi to myslím nezaznělo, ale když někdo razí tuto drastickou
separaci chování od samotných dat, často dodává, že takto je to přece definováno Evansem,
tedy autoritou,  v kanonické knize o <a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">Domain
Driven Designu</a>. Když se ptám, kde o tom Evans mluví, dozvím se, že Evans má objekty,
které mají svůj stav (vlastnosti)  a s objekty pracují speciální business-doménové
služby (chování). I když mám vůči DDD spoustu výhrad, zde Evanse špatně interpretují
– Evans by model, kde objekty mají jen stav a nemají žádné chování, nazval <a href="http://martinfowler.com/bliki/AnemicDomainModel.html">anemickým
modelem</a> – izolovaná data podepřená berličkami nesouvisejících globálních funkcí.
Business služby jsou, zjednodušeně řečeno, určeny pro zapsání složitější business
logiky, na které spolupracuje více objektů a žádný participující objekt není sám o
sobě přirozeným kandidátem, do kterého by bylo vhodné logiku situovat.
</p>
        <p>
Zde bych mohl pokračovat dále k rozdělení objektů v DDD, ke skutečnému významu vlastností
u objektu, co říká princip “tell, don't ask”, ale už teď mi původně krátký komentář
k SRP a DDD až moc nabobtnal. Když budete mít zájem o další naznačená témata, napište
prosím komentář k článku.
</p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=59132463-8265-453d-b94a-d44bc3a07878" />
      </body>
      <title>O &amp;scaron;patně ch&amp;aacute;pan&amp;eacute;m principu jedn&amp;eacute; odpovědnosti tř&amp;iacute;dy (SRP) a o zneuž&amp;iacute;v&amp;aacute;n&amp;iacute; my&amp;scaron;lenek Domain driven designu (DDD)</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,59132463-8265-453d-b94a-d44bc3a07878.aspx</guid>
      <link>http://blog.renestein.net/O+Scaronpatn%c4%9b+Chaacutepaneacutem+Principu+Jedneacute+Odpov%c4%9bdnosti+T%c5%99iacutedy+SRP+A+O+Zneu%c5%beiacutevaacuteniacute+Myscaronlenek+Domain+Driven+Designu+DDD.aspx</link>
      <pubDate>Sun, 05 Jun 2011 20:13:04 GMT</pubDate>
      <description>&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Dnes na twitteru &lt;a href="http://twitter.com/#!/DavidGrudl/status/77398502971424768"&gt;David
Grudl odkázal&lt;/a&gt; na debatu, která se &lt;a href="http://php.vrana.cz/prace-s-vlastnostmi-pomoci-metod.php#d-11965"&gt;týká
vlastností v PHP&lt;/a&gt;. O vlastnostech v PHP mluvit nechci, ale v tomto&amp;nbsp; příspěvku
se chci dotknout některých “dogmat”, které se ozývají stále častěji a které byly použity
jako univerzální kladivo na oponenty&amp;nbsp; i v odkazované diskuzi.
&lt;/p&gt;
&lt;p&gt;
Jedno zvláštní dogma se týká principu jedné odpovědnosti třídy (Single responsibility
principle). Tento princip říká, že třída by měla mít jednu přesně vymezenou odpovědnost,
která je v souladu s jejím názvem. I když na první přečtění se tento princip zdá neproblematický,
dá se zneužít jako univerzální kladivo. &lt;strong&gt;Dogmatici mi říkali, že jedna odpovědnost
si vynucuje, aby třída vždy měla právě jednu metodu, která tuto odpovědnost realizuje. &lt;/strong&gt;Není
nad přehledný svět objektových dogmatiků, kde objekt je jen stupidní kontajner na
jednu (de facto globální?) funkci.&lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Opakovn-zklad_119C2/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
Dogmatiky tohoto zvláštního ražení&amp;nbsp; zanedbejme jako ztracené případy a SRP obohaťme
o další vysvětlení, které říká, že třída by měla mít jen jeden důvod ke změně. Tento
princip je užitečný v tom, se snaží z aplikací odstranit všemocné božské (God) objekty,
které mnohdy už svým názvem signalizují, že řeší spoustu věcí. UniversalOrderAndInvoiceProcessor
oznamuje, že se bude měnit nejen, když se změní zpracování objednávek, ale také když
se změní zpracování faktur. Jednoduché, což? Proč o tomhle jednoduchém principu vůbec
dále mluvit?
&lt;/p&gt;
&lt;p&gt;
V diskuzi se o SRP &lt;a href="http://php.vrana.cz/prace-s-vlastnostmi-pomoci-metod.php#d-11965"&gt;mluví
(viz i příspěvky níže&lt;/a&gt;), ale diskutující tam ve&amp;nbsp; své argumentaci používají
něco, čemu na kurzech u SRP říkám falešné alternativy.
&lt;/p&gt;
&lt;p&gt;
Mějme stejně jako v diskusi svou třídu Image, která nese informace o obrázku. Obrázek
chceme uložit.
&lt;/p&gt;
&lt;p&gt;
Varianta 1, kdy obrázek nese informace a současně nabízí metodu Save, ve které uloží
data do souboru.
&lt;/p&gt;
&lt;script src="https://gist.github.com/1009256.js"&gt; &lt;/script&gt;
&lt;p&gt;
Co je v diskuzi vyčítáno této třídě? Porušuje princip jedné odpovědnosti, protože
podle některých (Jiří Knesl, Ondřej Mirteš)&amp;nbsp; řeší dvě věci najednou – &lt;strong&gt;nese
data o obrázku a současně data ukládá. &lt;/strong&gt;Souhlasím, že jde o porušení SRP,
ale hlavním důvodem je to, že metoda Save je napsána tak,&amp;nbsp; že třídu Image ukládáme &lt;strong&gt;vždy &lt;/strong&gt;do
souboru. Co když budeme chtít třídu Image uložit do nějakého “response” streamu na
webovém serveru, nebo uložit přímo do databáze? Tuto třídu skutečně budeme měnit ze
dvou důvodů – jednou, když přidáme nebo odebereme informace o obrázku a také, když
budeme chtít ukládat obrázek do databáze, musíme rozšířit stávající metodu Save, což
povede k tomu, že metoda bude mít v sobě nějaký podivný switch a&amp;nbsp; bude trpět
smíšenou odpovědností, protože bude dělat několik věcí najednou,&amp;nbsp; nebo můžeme
přidat novou samostatnou metodu SaveToDb. 
&lt;/p&gt;
&lt;p&gt;
Jedinou (!?) alternativou v diskuzi k tomuto postupu je vyvedení odpovědnosti za ukládání
do různých úložišť do samostatných objektů, které mohou být&amp;nbsp; skryty za jednotným
rozhraním.
&lt;/p&gt;
&lt;script src="https://gist.github.com/1009269.js"&gt; &lt;/script&gt;
&lt;p&gt;
Toto řešení důsledně separuje odpovědnosti, navíc je velmi snadné přidat další implementaci
rozhraní IImagePersistor, např. DbPersistor, který data uloží do databáze. Už v diskuzi
Jakub Vrána ale upozorňuje na to, že se mu nelíbí, jak se řešení komplikuje pro uživatele-vývojáře,
který s třídami bude pracovat, protože tento vývojář musí vědět, že existuje nějaký
IImagePersistor/FilePersistor odpovědný za uložení dat. Třída Image nestačí k tomu,
abyste dokázali vygenerovat data obrázku a uložit je, což může být ve vaší knihovně
častý scénář. Také bych rád poprvé v tomto článku připomněl princip OOP, ke kterému
se za chvíli vrátím, že &lt;strong&gt;objekt představuje jednotu svého stavu a chování,
které je pro tento stav definováno. &lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Psal jsem o falešných alternativách, můžeme najít i jiná řešení. Co ponechat
metodu Save ve třídě Image, ale z třídy Image udělat tzv kompozitor - objekt, který
skládá své chování tak, že využívá další pomocné objekty, na kterých závisí, a nabízí
intuitivní rozhraní pro klienty. &lt;/strong&gt;
&lt;/p&gt;
&lt;script src="https://gist.github.com/1009274.js"&gt; &lt;/script&gt;
&lt;p&gt;
Odpovědnosti jsou stále separovány a dokonce třída Image, náš kompozitor, dodržuje
pravidlo, které říká, že kompozitor by měl být jednodušší než suma funkcí jeho pomocných
objektů.&amp;nbsp; Klient třídy Image nemusí pracovat přímo s třídou FilePersistor, a
přitom nemáme kód pro ukládání do souboru přímo ve třídě Image. Problém je, že metoda
Save třídy Image vždy vytváří FilePersistor. Klient třídy Image si nemůže vyžádat
to námi dříve zmiňované ukládání obrázku do databáze, a navíc třída Image závisí na
jedné konkrétní třídě FilePersistor, u níž přímo volá konstruktor. &lt;strong&gt;V třídě
Image mixujeme vytváření grafu spolupracujících objektů se samotným použitím pomocných
objektů. Opět jde o dvě odpovědnosti, které bychom měli oddělit – SRP, nezapomeňme.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Nejprve ale zkusme vyřešit problém s tím, že klient nemůže ukládat data do databáze,
protože třída Image ukládá data vždy do souboru.
&lt;/p&gt;
&lt;script src="https://gist.github.com/1009285.js"&gt; &lt;/script&gt;
&lt;p&gt;
Jednoduše přidáme další variantu metody, která přijímá odkaz na IImagePersistor, v
našem případě třeba na DbPersistor. Původní metoda Save bez argumentů řeší ukládání
do souboru. Ukládání do souboru je nejčastější scénář, který je zvolen jako výchozí.
Stále ale tady máme problém s tím, že v metodě Save konstruujeme "natvrdo" FilePersistor.
A navíc naše API klientům trochu lže. V podtextu klientovi sděluje, že výchozí metoda
Save nemá žádné další závislosti, i když z implementace, !a jen z implementace!,&amp;nbsp;
je zřejmé, že jsme závislí na přítomnosti třídy FilePersistor. &lt;em&gt;Poznámka: V C#
4 můžeme použít volitelné argumenty u jedné metody, ale na principu této varianty
řešení se moc nemění.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Zkusme naše prozatím ulhané API vylepšit a dodržet SRP.&amp;nbsp; Oddělme nyní konstrukci
pomocných objektů, na kterých závisíme, od jejich použití v metodě Save. 
&lt;/p&gt;
&lt;script src="https://gist.github.com/1009297.js"&gt; &lt;/script&gt;
&lt;p&gt;
Objekt Image si nyní v konstruktoru vynucuje předání IIMagePersitoru. Když klient
IImagePersistor nepředá, objekt nezvznikne – sám konstruktor garantuje, že buď objekt
Image má vyplněny všechny závislosti, nebo vůbec nevznikne. Vytvořili jsme konstruktor,
který může použít a automaticky naplnit DI kontajner, nebo různé abstraktní továrny
registrované v DI kontajneru&amp;nbsp; apod. &lt;strong&gt;DI kontajner je přesně tím objektem,
který by měl být v aplikaci odpovědný za konstrukci grafu objektů,&lt;/strong&gt; v metodě
Save objektu Image injektovaný IImagePersistor jen používáme. SRP v praxi.
&lt;/p&gt;
&lt;p&gt;
Možný že ale v tomto případě je injektování závislostí přes konstruktor moc striktní.
Co když nám skutečně vyhovuje, že můžeme bez DI kontajneru vytvořit objekt Image,
který bude data ukládat do souboru. Pak můžeme využít injektování přes vlastnosti,
kdy příslušnou vlastnost po vzniku objektu vyplníme rozumnou výchozí hodnotou – v
našem případě instancí FilePersistoru. Poté ale platí, že třídu Image stále částečně
zatěžujete konstrukcí objektů…&lt;br&gt;
U většiny DI kontajnerů je preferováno injektování závislostí přes konstruktory, všechny,
které znám,&amp;nbsp; si ale poradí ale i s injektováním závislostí přes vlastností a
u &lt;a href="http://www.google.cz/search?hl=cs&amp;amp;source=hp&amp;amp;q=MEF+MSDN&amp;amp;aq=f&amp;amp;aqi=&amp;amp;aql=&amp;amp;oq="&gt;MEF&lt;/a&gt;u
bych řekl, že injektování závislostí pomocí vlastností hrají prim.
&lt;/p&gt;
&lt;script src="https://gist.github.com/1009315.js"&gt; &lt;/script&gt;
&lt;p&gt;
Všechny tyto varianty mají své výhody a nevýhody a asi nemusím zdůrazňovat, že ani
jedna není univerzálním kladivem. Varianty s injektováním závislostí (konstruktor,
metoda, vlastnost) jsou samozřejmě mnohem lépe testovatelné.
&lt;/p&gt;
&lt;p&gt;
Dokážu přidat i další příklady, ale chtěl jsem,&amp;nbsp; abyste viděli, že SRP není ani
nesmysl, ale ani princip, který by, podobně jako to zaznělo v diskuzi, sděloval –
existují jen dvě alternativy, jak rozdělovat odpovědnosti, a ZROVNA TA TVOJE JE ŠPATNĚ.
&lt;/p&gt;
&lt;p&gt;
A poslední&amp;nbsp; poznámka:
&lt;/p&gt;
&lt;p&gt;
Jiřé Knesl také v diskuzi uvedl: “ objekt buďto data reprezentuje (pak má settery/gettery),
nebo vykonává činnost (pak dostane data parametry)”. Tohle je podle mě&amp;nbsp; postoj
blízký hlavně některým Javistům, o čemž svědčí i podle mého soudu schematický a nevěrohodný &lt;a href="http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html"&gt;článek,
který se zabývá vlastnostmi v Javě&lt;/a&gt; a na který se J. Knesl odkazuje. Znovu připomínám,
že &lt;strong&gt;objekt představuje jednotu svého stavu a chování, které je pro tento stav
definováno.&amp;nbsp; &lt;/strong&gt;Objekt, který má jen gettery a settery, je ”krabičkou na
data”, pouhou strukturou známou i z neobjektových jazyků, a když má objekt jen metody,
tak jde o (v mnoha případech skutečně globální) funkce/procedury, které prefixujeme
názvem proměnné/třídy. V diskuzi to myslím nezaznělo, ale když někdo razí tuto drastickou
separaci chování od samotných dat, často dodává, že takto je to přece definováno Evansem,
tedy autoritou,&amp;nbsp; v kanonické knize o &lt;a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215"&gt;Domain
Driven Designu&lt;/a&gt;. Když se ptám, kde o tom Evans mluví, dozvím se, že Evans má objekty,
které mají svůj stav (vlastnosti)&amp;nbsp; a s objekty pracují speciální business-doménové
služby (chování). I když mám vůči DDD spoustu výhrad, zde Evanse špatně interpretují
– Evans by model, kde objekty mají jen stav a nemají žádné chování, nazval &lt;a href="http://martinfowler.com/bliki/AnemicDomainModel.html"&gt;anemickým
modelem&lt;/a&gt; – izolovaná data podepřená berličkami nesouvisejících globálních funkcí.
Business služby jsou, zjednodušeně řečeno, určeny pro zapsání složitější business
logiky, na které spolupracuje více objektů a žádný participující objekt není sám o
sobě přirozeným kandidátem, do kterého by bylo vhodné logiku situovat.
&lt;/p&gt;
&lt;p&gt;
Zde bych mohl pokračovat dále k rozdělení objektů v DDD, ke skutečnému významu vlastností
u objektu, co říká princip “tell, don't ask”, ale už teď mi původně krátký komentář
k SRP a DDD až moc nabobtnal. Když budete mít zájem o další naznačená témata, napište
prosím komentář k článku.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=59132463-8265-453d-b94a-d44bc3a07878" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,59132463-8265-453d-b94a-d44bc3a07878.aspx</comments>
      <category>Analytické drobky</category>
      <category>C#</category>
      <category>Návrhové vzory</category>
      <category>UML</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=d106e718-5c10-4f2a-8de5-70979fbdd7bc</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,d106e718-5c10-4f2a-8de5-70979fbdd7bc.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,d106e718-5c10-4f2a-8de5-70979fbdd7bc.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=d106e718-5c10-4f2a-8de5-70979fbdd7bc</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Dostal jsme dotaz, jak si poradit s odstraňováním chyb u starší a rozsáhlé aplikace.
Když jsem odepisoval, uvědomil jsem si, že sepisuju jakési “triviální  desatero
vývoje”", které se snažím už dlouhou dobu svému okolí vtloukat dohlavy. I když jde
o triviální zásady, budu příště odkazovat raději na tento příspěvek, než abych vše
opakoval pokaždé znovu. Jméno firmy je v textu nahrazenou souslovím “anonymní firma”.
</p>
        <p>
          <em>“Zdravím,<br />
to je na hodně dlouhý příspěvek.<br />
Alespoň tedy:</em>
        </p>
        <p>
          <em>1) Je nutné zrušit umělou hranici mezi vývojáři a testery. Žádná výměna informací
přes šéfy oddělení nebo pověřené osoby.</em>
        </p>
        <p>
          <em>2) Na každou objevenou chybu musí být napsán automatický test, který zajistí,
že chyba neprobublá do dalších releasů. Bez toho žádné organizační opatření nefunguje.
Bez napsaného testu se chyba nepovažuje za odstraněnou, ale jen za náhodou se nyní
neprojevující.</em>
        </p>
        <p>
          <em>3) Vytvořit malé sebeorganizující týmy odpovědné za určitou část projektu (nastálo,
nebo do dalšího releasu). V čele team leader, který garantuje kvalitu. Team leader
je k dispozici i testerům a řeší nesrovnalosti v analýze a systémovém designu. S dalšími
team leadery řeší problémy integrace různých částí projektu. <strong>Team leader ale
stále většinu času kóduje, není to embryo vychovávané pro střední management</strong>.</em>
        </p>
        <p>
          <em>4) Je potřeba postupně napsat velké množství automatických testů (unit, integrační,
akceptační) tak, aby se testeři věnovali hlavně novým záležitostem v releasu a aby
vývojáři ani testeři nebyli obětí "ručně prováděných" regresních testů, které mají
formu nikdy nekončícího debugování. <strong>Tím se i zkrátí doba, kterou "anonymní
firma" nutně musí trávit opakovaným debugováním a "ručním" nalézáním příčin chyb.</strong> Automatizované
testy představují práci, která se na projektech vyplatí, a navíc jde i o mnohem levnější
řešení problému, než nabírání dalších a dalších testerů.</em>
        </p>
        <p>
          <em>5) Nedávat žádné fixní odhady na odstranění chyb ani nikoho exkluzivně nealokovat
jen na odstraňování chyb. Vývojář není a přes různé manažerské poučky ani nebude anonymní
zdroj, který sebereme z jiného projektu, posadíme k aplikaci, kterou nezná, ale u
které dostane befelem, že za jednu normohodinu musí odstranit 20 bugů. Tato kouzla
fungují jenom v Excelu. V reálném světě vývojář těch 20 bugů neodstraní, ani když
ho posadíte do open space, který  je oblepen motivačním majstrštykem vytisknutým
z PowerPointu nejlepším absolventem MBA.<br /><br />
Pokud se objeví chyba, chopí se jí člověk, který za danou oblast odpovídá (konflikty
přinejhorším vyřeší team leadeři). Vývojář neustále čte a refaktorizuje kód, pokud
možno ihned také odstraňuje chyby . A jsme opět u testů - dokud ty automatizované
testy mít nebudete, vývojáři do kódu raději nezasahují, protože nevědí, kde všude
se změna projeví a raději neriskují další možnou příčinu pádu aplikace po nasazení
u zákazníka. A psát použitelné, ne jen formální-švejkovské testy, kdy se hodnotí "jen
code coverage", se musí všichni vývojáři naučit a nějakou dobu to zabere.</em>
        </p>
        <p>
          <em>Mám zkušenost s 12 let starou aplikací psanou původně pro VB, poté čátečně přepsanou
na .Net Framework,  která byla po 9 letech <strong>postupně </strong>obalena
testy, a ani dnes sice nejde o žádnou vývojářskou lahůdku, ale pracuje se na ní beze
strachu, co při každé změně v aplikaci zničíme. Nic jiného než to, co píšu výše, se
mi neosvědčilo.</em>
        </p>
        <p>
          <em>A pak další záležitosti jako (nutné) bonbonky:<br /></em>
        </p>
        <ul>
          <li>
            <em>Neztrácet čas “mergováním” změn v něčem tak zastaralém a nepohodlném jako je Subversion.
V Mercurialu (GITu) je propagace změn z vývojové větve do hlavní (a zpět) otázka chvíle.
V Subversion ani TFS jsem po pár zkušenostech raději moc "branchů" nedělal.<br /></em>
          </li>
          <li>
            <em>Automatické buildy spojené s již napsanými testy.<br /></em>
          </li>
          <li>
            <em>Automatické nasazení nové verze aplikace, aby testeři nemuseli pátrat, kde seženou
novou verzi a také, aby nasazení do produkčního prostředí neznamenalo 3denní práci
party lidí, kteří se metodou pokus-omyl snaží dostat aplikaci do použitelného stavu
u zákazníka.<br /></em>
          </li>
          <li>
            <em>Alespoň u nováčků code review, abyste rychle odstranili jejich špatné návyky.<br /></em>
          </li>
          <li>
            <em>Statická analýza kódu.</em>
          </li>
        </ul>
        <p>
          <em>A dovolím si jednu soukromou poznámku k "anonymní firmě" - pokud možno zredukovat/vyhodit
všechny těžkotonážní, neskutečně drahé a pro vývojáře zabijácké nápady se zavedením
nejhorší možné formy vodopádu  - analýza-&gt;samostatný systémový design-&gt;vývoj-&gt;testy,
v jehož bludném pádu se bude produkovat množství dokumentů, navíc rychlokvašenými
analytiky/designery, v mizerné kvalitě a bez vazby na skutečné potřeby projektu. Analýza
a systémový design jsou fáze projektu, které pomáhají jen do doby, než se jich chytí
nějaký exot, který nikdy žádnou aplikaci nevyvíjel a který si myslí, že analytická
práce spočívá ve štosování nahodilých myšlenek zákazníka do příslušné šablony pro
use case. Což je dle mých zkušeností většina “čistých”, míněno vývojem nedotčených,
analytiků na pracovním trhu.</em>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=d106e718-5c10-4f2a-8de5-70979fbdd7bc" />
      </body>
      <title>P&amp;aacute;r trivi&amp;aacute;ln&amp;iacute;ch pozn&amp;aacute;mek k v&amp;yacute;voji aplikac&amp;iacute;</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,d106e718-5c10-4f2a-8de5-70979fbdd7bc.aspx</guid>
      <link>http://blog.renestein.net/Paacuter+Triviaacutelniacutech+Poznaacutemek+K+Vyacutevoji+Aplikaciacute.aspx</link>
      <pubDate>Mon, 30 May 2011 08:31:24 GMT</pubDate>
      <description>&lt;p&gt;
Dostal jsme dotaz, jak si poradit s odstraňováním chyb u starší a rozsáhlé aplikace.
Když jsem odepisoval, uvědomil jsem si, že sepisuju jakési “triviální&amp;nbsp; desatero
vývoje”", které se snažím už dlouhou dobu svému okolí vtloukat dohlavy. I když jde
o triviální zásady, budu příště odkazovat raději na tento příspěvek, než abych vše
opakoval pokaždé znovu. Jméno firmy je v textu nahrazenou souslovím “anonymní firma”.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;“Zdravím,&lt;br&gt;
to je na hodně dlouhý příspěvek.&lt;br&gt;
Alespoň tedy:&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;1) Je nutné zrušit umělou hranici mezi vývojáři a testery. Žádná výměna informací
přes šéfy oddělení nebo pověřené osoby.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;2) Na každou objevenou chybu musí být napsán automatický test, který zajistí,
že chyba neprobublá do dalších releasů. Bez toho žádné organizační opatření nefunguje.
Bez napsaného testu se chyba nepovažuje za odstraněnou, ale jen za náhodou se nyní
neprojevující.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;3) Vytvořit malé sebeorganizující týmy odpovědné za určitou část projektu (nastálo,
nebo do dalšího releasu). V čele team leader, který garantuje kvalitu. Team leader
je k dispozici i testerům a řeší nesrovnalosti v analýze a systémovém designu. S dalšími
team leadery řeší problémy integrace různých částí projektu. &lt;strong&gt;Team leader ale
stále většinu času kóduje, není to embryo vychovávané pro střední management&lt;/strong&gt;.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;4) Je potřeba postupně napsat velké množství automatických testů (unit, integrační,
akceptační) tak, aby se testeři věnovali hlavně novým záležitostem v releasu a aby
vývojáři ani testeři nebyli obětí "ručně prováděných" regresních testů, které mají
formu nikdy nekončícího debugování. &lt;strong&gt;Tím se i zkrátí doba, kterou "anonymní
firma" nutně musí trávit opakovaným debugováním a "ručním" nalézáním příčin chyb.&lt;/strong&gt; Automatizované
testy představují práci, která se na projektech vyplatí, a navíc jde i o mnohem levnější
řešení problému, než nabírání dalších a dalších testerů.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;5) Nedávat žádné fixní odhady na odstranění chyb ani nikoho exkluzivně nealokovat
jen na odstraňování chyb. Vývojář není a přes různé manažerské poučky ani nebude anonymní
zdroj, který sebereme z jiného projektu, posadíme k aplikaci, kterou nezná, ale u
které dostane befelem, že za jednu normohodinu musí odstranit 20 bugů. Tato kouzla
fungují jenom v Excelu. V reálném světě vývojář těch 20 bugů neodstraní, ani když
ho posadíte do open space, který&amp;nbsp; je oblepen motivačním majstrštykem vytisknutým
z PowerPointu nejlepším absolventem MBA.&lt;br&gt;
&lt;br&gt;
Pokud se objeví chyba, chopí se jí člověk, který za danou oblast odpovídá (konflikty
přinejhorším vyřeší team leadeři). Vývojář neustále čte a refaktorizuje kód, pokud
možno ihned také odstraňuje chyby . A jsme opět u testů - dokud ty automatizované
testy mít nebudete, vývojáři do kódu raději nezasahují, protože nevědí, kde všude
se změna projeví a raději neriskují další možnou příčinu pádu aplikace po nasazení
u zákazníka. A psát použitelné, ne jen formální-švejkovské testy, kdy se hodnotí "jen
code coverage", se musí všichni vývojáři naučit a nějakou dobu to zabere.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Mám zkušenost s 12 let starou aplikací psanou původně pro VB, poté čátečně přepsanou
na .Net Framework,&amp;nbsp; která byla po 9 letech &lt;strong&gt;postupně &lt;/strong&gt;obalena
testy, a ani dnes sice nejde o žádnou vývojářskou lahůdku, ale pracuje se na ní beze
strachu, co při každé změně v aplikaci zničíme. Nic jiného než to, co píšu výše, se
mi neosvědčilo.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;A pak další záležitosti jako (nutné) bonbonky:&lt;br&gt;
&lt;/p&gt;
&gt; 
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Neztrácet čas “mergováním” změn v něčem tak zastaralém a nepohodlném jako je Subversion.
V Mercurialu (GITu) je propagace změn z vývojové větve do hlavní (a zpět) otázka chvíle.
V Subversion ani TFS jsem po pár zkušenostech raději moc "branchů" nedělal.&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
&lt;em&gt;Automatické buildy spojené s již napsanými testy.&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
&lt;em&gt;Automatické nasazení nové verze aplikace, aby testeři nemuseli pátrat, kde seženou
novou verzi a také, aby nasazení do produkčního prostředí neznamenalo 3denní práci
party lidí, kteří se metodou pokus-omyl snaží dostat aplikaci do použitelného stavu
u zákazníka.&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
&lt;em&gt;Alespoň u nováčků code review, abyste rychle odstranili jejich špatné návyky.&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
&lt;em&gt;Statická analýza kódu.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;em&gt;A dovolím si jednu soukromou poznámku k "anonymní firmě" - pokud možno zredukovat/vyhodit
všechny těžkotonážní, neskutečně drahé a pro vývojáře zabijácké nápady se zavedením
nejhorší možné formy vodopádu&amp;nbsp; - analýza-&amp;gt;samostatný systémový design-&amp;gt;vývoj-&amp;gt;testy,
v jehož bludném pádu se bude produkovat množství dokumentů, navíc rychlokvašenými
analytiky/designery, v mizerné kvalitě a bez vazby na skutečné potřeby projektu. Analýza
a systémový design jsou fáze projektu, které pomáhají jen do doby, než se jich chytí
nějaký exot, který nikdy žádnou aplikaci nevyvíjel a který si myslí, že analytická
práce spočívá ve štosování nahodilých myšlenek zákazníka do příslušné šablony pro
use case. Což je dle mých zkušeností většina “čistých”, míněno vývojem nedotčených,
analytiků na pracovním trhu.&lt;/em&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=d106e718-5c10-4f2a-8de5-70979fbdd7bc" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,d106e718-5c10-4f2a-8de5-70979fbdd7bc.aspx</comments>
      <category>Analytické drobky</category>
      <category>Návrhové vzory</category>
      <category>Ostatní</category>
      <category>UML</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=f901aabc-0275-44ef-9865-19317ab5422a</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,f901aabc-0275-44ef-9865-19317ab5422a.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=f901aabc-0275-44ef-9865-19317ab5422a</wfw:commentRss>
      <title>Pozv&amp;aacute;nka na kurzy objektov&amp;yacute;ch principů a n&amp;aacute;vrhov&amp;yacute;ch vzorů &amp;ndash; podzim 2011</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,f901aabc-0275-44ef-9865-19317ab5422a.aspx</guid>
      <link>http://blog.renestein.net/Pozvaacutenka+Na+Kurzy+Objektovyacutech+Princip%c5%af+A+Naacutevrhovyacutech+Vzor%c5%af+Ndash+Podzim+2011.aspx</link>
      <pubDate>Mon, 16 May 2011 10:15:38 GMT</pubDate>
      <description>&lt;p&gt;
&lt;p&gt;
Opět vás všechny zvu na pravidelný podzimní běh kurzů &lt;strong&gt;Objektovými principy
a návrhovými vzory řízený design a vývoj kvalitních aplikací 1 &lt;/strong&gt;a &lt;strong&gt;Pokročilé
návrhové vzory a objektové principy 2. &lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Novinkou v tomto roce je &lt;em&gt;kurz pro začátečníky&lt;/em&gt; nazvaný Základy objektově
orientovaného návrhu a vývoje. Někteří z vás ho mohli během posledních dvou let absolvovat
ve formě inhouse kurzu pod interním názvem UML 0. Kurz UML 0 vznikl velmi spontánně
jako reakce na požadavky některých firem, které nechtěly rovnou absolvovat stávající
kurzy. &lt;/strong&gt;Nyní je vycizelované UML 0 dostupné i jako veřejný kurz, protože v
emailech se opakovaly žádosti o jeho veřejnou formu od lidí, kteří kurz absolvovali
a nyní na něj chtěli poslat své kolegy.&lt;br&gt;
&lt;br&gt;
O tomto novém kurzu naleznete podrobné informace níže v této pozvánce. &lt;strong&gt;Znovu
opakuji, že se jedná o &lt;em&gt;kurz pro začátečníky&lt;/em&gt;, který dříve v nabídce nebyl,
protože kurzy &lt;strong&gt;Objektovými principy a návrhovými vzory řízený design a vývoj
kvalitních aplikací 1 &lt;/strong&gt;a &lt;strong&gt;Pokročilé návrhové vzory a objektové principy
2 byly a stále jsou určeny pro lidi, kteří základy znají&lt;/strong&gt;. Nenechte se ale
zmást “kódovým” názvem nového kurzu (UML 0), účastníci bývají překvapeni, že s UML
na kurzu zacházíme zcela pragmaticky a bez posvátné úcty, ale i bez módních předsudků
a rychlých odsudků. UML bereme jako nástroj, a ne jako samoúčelný cíl našeho snažení
na kurzu.&lt;/strong&gt; 
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;b&gt;Veřejný kurz Základy objektově orientovaného návrhu a vývoje (UML 0)&lt;/b&gt; 
&lt;p&gt;
Datum konání kurzu: &lt;strong&gt;19. 9. – 21. 9. 2011&lt;/strong&gt; 
&lt;p&gt;
Místo konání&lt;strong&gt;: &lt;/strong&gt; 
&lt;p&gt;
&lt;a href="http://www.tutor.cz/"&gt;Školící středisko Tutor&lt;/a&gt; 
&lt;p&gt;
U Půjčovny 2&lt;br&gt;
110 00 Praha 1 
&lt;p&gt;
&lt;em&gt;Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.&lt;/em&gt; 
&lt;p&gt;
&lt;a href="http://renestein.net/Nabidka.aspx#skoleniOOP0"&gt;Podrobné informace o kurzu
a možnost přihlásit se na kurz&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://renestein.net/Skoleni-Zaklady-Objektove-Orientovaneho-Navrhu-UML-0.aspx"&gt;Program
kurzu&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://renestein.net/Casto-Kladene-Dotazy-Kurzy-FAQ.aspx"&gt;FAQ - často kladené
dotazy ke kurzům&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;b&gt;Veřejný kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních
aplikací 1&lt;/b&gt; 
&lt;p&gt;
Datum konání kurzu: &lt;strong&gt;10. 10. – 12. 10. 2011&lt;/strong&gt; 
&lt;p&gt;
Místo konání&lt;strong&gt;: &lt;/strong&gt; 
&lt;p&gt;
&lt;a href="http://www.tutor.cz/"&gt;Školící středisko Tutor&lt;/a&gt; 
&lt;p&gt;
U Půjčovny 2&lt;br&gt;
110 00 Praha 1 
&lt;p&gt;
&lt;em&gt;Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.&lt;/em&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=d6fd9894-f5cd-4d7d-9e78-53974f98d52d&amp;url=http%3a%2f%2fwww.renestein.net%2fNabidka.aspx%23skoleni"&gt;Podrobné
informace o kurzu a možnost přihlásit se na kurz&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=d6fd9894-f5cd-4d7d-9e78-53974f98d52d&amp;url=http%3a%2f%2fwww.renestein.net%2fSkoleni-UML-OOP-Navrhove-vzory-1.aspx"&gt;Program
kurzu&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/ct.ashx?id=d6fd9894-f5cd-4d7d-9e78-53974f98d52d&amp;url=http%3a%2f%2fwww.renestein.net%2fOhlasy-Ucastniku-Na-Kurzy.aspx"&gt;Výběr
z ohlasů na kurz&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://renestein.net/Casto-Kladene-Dotazy-Kurzy-FAQ.aspx"&gt;FAQ - často kladené
dotazy ke kurzům&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;b&gt;Veřejný kurz Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních
aplikací 2&lt;/b&gt; 
&lt;p&gt;
Datum konání kurzu: &lt;strong&gt;24. 10. – 26. 10. 2011&lt;/strong&gt; 
&lt;p&gt;
Místo konání&lt;strong&gt;: &lt;/strong&gt; 
&lt;p&gt;
&lt;a href="http://www.tutor.cz/"&gt;Školící středisko Tutor&lt;/a&gt; 
&lt;p&gt;
U Půjčovny 2&lt;br&gt;
110 00 Praha 1 
&lt;p&gt;
&lt;em&gt;Po celý den máme k dispozici wifi připojení a samozřejmě také teplé a studené
nápoje. V ceně kurzu jsou obědy v hotelu.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.renestein.net/Nabidka.aspx#SkoleniOOP2"&gt;Podrobné informace o kurzu
a možnost přihlásit se na kurz&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://www.renestein.net/Skoleni-Navrhove-vzory-2.aspx"&gt;Program kurzu&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://www.renestein.net/Ohlasy-Ucastniku-Na-Kurzy.aspx"&gt;Výběr z ohlasů na
kurzy&lt;/a&gt; 
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://renestein.net/Casto-Kladene-Dotazy-Kurzy-FAQ.aspx"&gt;FAQ - často kladené
dotazy ke kurzům&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;hr&gt;
&lt;p&gt;
&lt;b&gt;Program nového kurzu Základy objektově orientovaného návrhu a vývoje (UML 0)&lt;/b&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Předpokládané znalosti účastníků&lt;/strong&gt;
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Základní přehled o etapách vývoje projektu. 
&lt;br&gt;
&lt;li&gt;
Vhodné je mít nějaké vlastní zkušenosti z analýzy a vývoje projektů, abychom mohli
porovnat různé postupy a doporučení a jejich použitelnost v praxi. 
&lt;br&gt;
&lt;li&gt;
Chuť se učit.;) Schopnost pohlédnout na některá domněle známá témata bez předsudků. 
&lt;br&gt;
&lt;li&gt;
Částečná znalost UML je vhodná, ale u tohoto kurzu není vyžadována. Vhodná je hlavně
pro konfrontaci vlastních zkušeností s tím, co zazní o použitelnosti různých částí
UML na kurzu. 
&lt;br&gt;
&lt;li&gt;
Nenávist ke kariéře zručného "bušiče", nikým nerespektovaného projektového vedoucího
(tzv. sekretářky 2.0) a neschopného analytika / vývojáře. 
&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&lt;strong&gt;Obecné informace ke kurzu&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Pro vývojáře se u konstrukcí a prvků jazyka UML, které jsou považovány za analytické,
dělají časté odbočky do kódu, aby vývojáři pochopili, že UML ani principy OOP nejsou
nějaké nesmyslné abstrakce, ale užitečné konstrukce, které sami v programovacích jazycích
používají denně. U role analytika stále zdůrazňuji, jaké znalosti z oblasti vývoje
aplikací musí analytik mít, aby byl pro projekt užitečný a nevytvářel jen dokumentaci
pro dokumentaci, kterou vývojáři nevyužijí a (až příliš často oprávněně) ji považují
za nesmyslnou, drahou a hlavně vyvíjenému projektu nic nepřinášející. Kurz je určen
pro vývojáře, systémové designery, analytiky a projektové manažery, kteří se chtějí
seznámit se základními principy objektového programování a s modelováním v jazyce
UML. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Program školení &lt;/strong&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Proč má dnes UML v některých kruzích špatnou pověst? Musíte být těžkotonážní rytíři
cválající na drahých CASE nástrojích a neživotných formálních projektových metodikách,
nebo si vystačíte s nástroji a postupy, které zachytí vaše myšlenky, ale nenutí vás
přizpůsobovat se "Jen Tomu Jedinému Pravému Stylu Návrhu A Vývoje"?&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Dostali jste poptávku, máte za pár dní dodat nabídku a v seznamu svých dovedností
nenalézáte jasnovidectví ani nemáte po ruce čarovnou skleněnou kouli, abyste zákazníkovi
do nabídky vyvěštili konečnou cenu i datum dokončení projektu? Co dělat v počáteční
fázi projektu, kdy ještě ani nevíte, jestli budete projekt vyvíjet? 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Požadavky na systém. Jak je to s případy užití? Má vlastní zrychlená funkční specifikace
bez zbytečných formalit. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Rozsáhlé ukázky fukčních specifikací z projektů. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Diagram tříd v UML. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Rozdíl mezi analytickým diagramem tříd a diagramem tříd vytvářeným ve fázi systémového
designu - existuje takový rozdíl, nebo jde jen o další hloupý mýtus? 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Třída - základní principy OOP, operace, atributy, viditelnost členů třídy. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Vztahy mezi elementy diagramu (asociace, agregace, generalizace, závislost, realizace)
– vše vykládáno na konkrétních příkladech z praxe + ukázky nejčastějších chyb, se
kterými jsem se setkal. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Dobře zapamatovatelné principy návrhu známé pod zkratkou SOLID v příkladech. Unit
testy, integrační testy, akceptační testy - skutečně si stále myslíte, že se bez nich
na projektech obejdete? 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Nejen SOLIDní principy stojí v pozadí návrhu aplikací... 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Nenásilný přechod k jednoduchým návrhovým vzorům. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Příklady složitých diagramů tříd. Jak je udržovat v souladu s napsaným kódem? A musíme
je udržovat? Co se na projektech vyplatí dělat a co projekt spolehlivě zabije? 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Objektový diagram + příklady. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Diagramy a diagramy interakce. Příklady. Typy projektů, pro které se tyto diagramy
hodí. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Vysvětlení stavových diagramů + výhody aplikací řízených přesně definovanými stavovými
automaty. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Diagram aktivit - modelování složitých business procesů v organizaci. Hrajete si s
diagramem aktivit rádi, ale ocení to Váš zákazník? 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Vrstvy a moduly v aplikaci – architektura aplikace. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Relační a objektový svět? Stále jediné možné partnerství z rozumu? 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Nasazení aplikace – výklad Component &amp; Deployment diagramů. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
OOP a jeho vztah UML. Vztah UML a OOP k projektové praxi a realitě. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Výhody a nevýhody UML – vyzdvižení nejvíce používaných postupů, odhození nepotřebné
veteše z jazyka UML. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Odpovědi na dotazy frekventantů kurzu. 
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;
Těším se s Vámi na setkání na kurzu!
&lt;/p&gt;
&lt;p&gt;
René Stein 
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=f901aabc-0275-44ef-9865-19317ab5422a" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,f901aabc-0275-44ef-9865-19317ab5422a.aspx</comments>
      <category>Analytické drobky</category>
      <category>Kurzy UML a OOP</category>
      <category>Návrhové vzory</category>
      <category>UML</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=1ab0ecc7-7a79-4e17-b2f8-358bd7713695</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,1ab0ecc7-7a79-4e17-b2f8-358bd7713695.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,1ab0ecc7-7a79-4e17-b2f8-358bd7713695.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=1ab0ecc7-7a79-4e17-b2f8-358bd7713695</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
V <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">předchozích
článcích</a> jsme si vytvořili miniframework pro <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">view
modely</a>   a ukázali si hostitele <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">našich
view modelů</a>. Přišel čas naše znalosti, idiomy a návrhové vzory zakódované ve formě
aplikační infrastruktury v našem miniframeworku využít při tvorbě konkrétní aplikace.
Pro účely tohoto článku i následujících článků jsem se rozhodl, že vytvoříme aplikaci,
která nám dovolí spravovat vlastní blog na doméně <a href="https://posterous.com/">Posterous</a> s
využitím <a href="http://posterousapi.codeplex.com/releases/view/55736#DownloadId=167194">Posterous
API</a>.
</p>
        <p>
Hlavní případy užití, které budeme v aplikaci podporovat.
</p>
        <ol>
          <li>
Přihlášení uživatele ke svému účtu  - téma dnešního článku.<br /><br /></li>
          <li>
Zobrazení seznamu blogů, které patří přihlášenému uživateli.<br /><br /></li>
          <li>
Zobrazení seznamu příspěvků na vybraném blogu.<br /><br /></li>
          <li>
Zobrazení detailu příspěvku na blogu.<br /><br /></li>
          <li>
Úprava stávajícího příspěvku na blogu.<br /><br /></li>
          <li>
Zadání nového příspěvku na blog.<br /></li>
        </ol>
        <p>
Jako vždy nás tato prozatím letmo načrtnutá témata dovedou k dalším podivným zákoutím
vývoje WP7 aplikací  a my se z nich s úsměvem záludnostmi WP7 <strike>poučeného
idiota  </strike>zoceleného harcovníka pokusíme dostat.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png" />.
</p>
        <p>
Skutečně vás nechci urážet popisem klikání ve Visual Studiu ani popisem základů XAMLu,
“data bindingu”, “behaviors”, takže jen napíšu, že byste před vytvářením aplikace
měli:
</p>
        <ol>
          <li>
Stáhnout si a nainstalovat <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=04704acf-a63a-4f97-952c-8b51b34b00ce&amp;displaylang=en">Windows
Phone Developer Tools.</a><br /><br /></li>
          <li>
Ve Visual Studiu založte nový projekt Windows Phone Application – nejlepší bude, když
ho pojmenujete jako já <em>RStein.PosterousReader.WP</em>, abyste nebyli zmateni názvy
jmenných prostorů dále v článku.<br /><br /><a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_1.png" width="244" height="170" /></a><br />
  
</li>
          <li>
Vývojářský život je na tomto projektu jednodušší o to, že k práci s Posterous API
použijeme můj <a href="http://posterousapi.codeplex.com/releases/view/55736#DownloadId=167194">C#
Posterous API Wrapper pro WP7</a>.  Po stažení přidejte referenci na knihovnu <em>RStein.Posterous.API.SLM </em>do
svého projektu.<br />
A i když to dnes ještě není tak nutné, <a href="https://posterous.com/">zřiďte si
na Posterous vlastní účet</a>, abyste mohli aplikaci později testovat na reálných
datech. C# Posterous API pro nás v triádě Model-View-ViewModel bude představovat model,
což má pro nás výhodu, že se můžeme stále soustředit na view a view modely, o které
šlo i v předchozích článcích, a model můžeme považovat za černou skříňku.<br /><br /></li>
          <li>
V novém projektu vytvořte hlavně dvě nové složky View a ViewModels. Na obrázku jsou
červeně podtrženy další složky, které si již dnes doporučuju přidat do projektu 
- Behaviors, Extensions, HostServices, Icons, SpecialTypes, UI, UIServices a hlavně
ViewModels a Views.<br /><br /><br /><a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_7.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_2.png" width="94" height="244" /></a><br /><br /></li>
          <li>
Předpokládám, že jste schopni do svého projektu vložit kód tříd, které jsem popisoval
v předchozích článcích. Seznam předchozích článků s výpisy kódu naleznete na konci
tohoto článku.</li>
        </ol>
        <p>
Dnes vytvoříme přihlašovací obrazovku do naší aplikace. Pro lepší představu je zde
obrazovka, kterou byste měli mít hotovou na konci dnešního článku.
</p>
        <p>
          <img src="http://blog.renestein.net/content/binary/Windows-Live-Writer/C-Posterous-API-.3--s-podporou-i-pro-WP7_D37E/image_2.png" width="379" height="633" />
        </p>
        <p>
  
</p>
        <p>
Nejprve určíme, které funkce musí obrazovka a její podkladový kód zvládat: 
</p>
        <ol>
          <li>
Přihlašovací obrazovka se zobrazí ihned po startu aplikace.<br /><br /></li>
          <li>
Uživateli dovolíme zadat přihlašovací jméno a heslo.<br /><br /></li>
          <li>
Jestliže není uživatelské jméno vyplněno (prázdný řetězec) a/nebo není vyplněno heslo,
tlačítko Přihlásit se je neaktivní.<br /><br /></li>
          <li>
Jestliže dojde k <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">“tombstoningu</a>”
stránky, bude jméno i heslo po návratu z “tombstonovaného” stavu zachováno – ověříme
si tak poprvé in vivo, že <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">naše
třída ViewModelBase podporuje “tombstoning” přesně dle našich požadavků</a>.<br /><br /></li>
          <li>
Po návratu na přihlašovací obrazovku z jiné části aplikace bude zachován jen obsah
textového pole “uživatelské jméno”, textové pole “heslo” bude prázdné.<br /><br /></li>
          <li>
Po kliknutí na tlačítko Přihlásit nebudeme zadané jméno a heslo ihned ověřovat, ale
uložíme oba údaje  pro použití na dalších stránkách aplikace. Poté přesměrujeme
uživatele na další stránku se seznamem blogů, kde bude jméno a heslo využito k získání
seznamu blogů uživatele. Důvodem je to, že v Posterous API se jméno a heslo zasílá
při každém webovém požadavku, žádné jednorázové přihlášení neexistuje a nemá smysl
generovat nějaký “dummy” požadavek jen pro ověření hesla. Jestliže se na stránce se
seznamem blogů, na kterou z přihlašovací obrazovky přesměrováváme, data kvůli neplatným
přihlašovacím údajům získat nepodaří, aplikace nás vrátí na přihlašovací obrazovku.
Vytvoření stránky se seznamem blogů bude téma dalšího článku.<br /></li>
        </ol>
        <p>
A začínáme: 
</p>
        <p>
Do složky Views vložte nové View pro přihlášení uživatele. V dialogu Add new item
vyberte Windows Phone Portrait Page a pojmenujte ji MainLoginView.xaml.
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_9.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_3.png" width="244" height="170" />
          </a>
        </p>
        <p>
Jedná se o úvodní  stránku aplikace, a proto v deskriptoru WP7 aplikace nazvaném
WAMppManifest.xml, který naleznete v projektové složce Properties, změníme startovací
stránku na View/mainLoginView.xaml. <script src="https://gist.github.com/793066.js"></script></p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_13.png">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_5.png" width="244" height="154" />
          </a>
        </p>
        <p>
I když to není u přihlašovacího dialogu nutné, v dnešním článku si ukážeme, jak můžeme
jednoduše složit jedno view z dalších nezávislých view a také to, že view nemusí být
jen stránka (Page), ale i “User Control”. Naše MainLoginView bude zobrazovat titulek
aplikace (Posterous klient), titulek stránky (Přihlášení) , ale textová pole “heslo”,
“uživatelské jméno” a tlačítko “Přihlásit" se” bude obsahovat “user control” LoginView,
který můžeme použít jako součást i zcela jiného view (stránky) v aplikaci.  Do
složky Views přidejte Windows Phone User Control a nazvěte jej LoginView.xaml. 
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_15.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_6.png" width="244" height="170" />
          </a>
        </p>
        <p>
Zkompilujte (Build) “solution”. 
</p>
        <p>
Do view MainLoginView vložte tento kód: 
</p>
        <p>
          <script src="http://gist.github.com/793080.js">
          </script>
        </p>
        <p>
Jak jsem zmiňoval v <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">jednom
z předešlých článků</a>, všechny stránky v aplikaci by měly být potomkem naší třídy <a href="https://gist.github.com/763320">PageBase</a>,
která je hostitelem pro view modely. Proto je naše stránka uzavřena v elementu <em>&lt;controlex:PageBase&gt;</em>. 
XML jmenný prostor controleex je u mě namapován na xmlns:controlex="clr-namespace:RStein.PosterousReader.WP.UI".
V projektovém adresáři UI musíte mít tedy třídu PageBase.
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_19.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_8.png" width="244" height="154" />
          </a>
        </p>
        <p>
Také v “code behind souboru” musíte třídu MainLoginView učinit potomkem PageBase.
</p>
        <script src="https://gist.github.com/793085.js">
        </script>
        <p>
Hlavní xaml pro přihlášení uživatele obsahuje “User Control” LoginView, na který se
v MainLoginView odkazujeme. <em>(&lt;views:LoginView Grid.Row="1"&gt;&lt;/views:LoginView&gt;</em>). 
XML jmenný prostor <em>views</em> je mapován na jmenný prostor <em>RStein.PosterousReader.WP.Views </em>v
C# (<em>xmlns:views="clr-namespace:RStein.PosterousReader.WP.Views</em>) – v našem
případě tedy na projektový adresář Views.
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_17.png">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_7.png" width="244" height="154" />
          </a>
        </p>
        <p>
Do view s názvem LoginView vložte následující XAML:
</p>
        <script src="https://gist.github.com/793102.js">
        </script>
        <p>
Jak bylo vidět na snímku obrazovky na počátku článku, LoginView obsahuje hlavně textové
pole pro zadání jména uživatele (txtName) a prvek pro zadání hesla uživatele (txtPassword)
a tlačítko “Přihlásit se”. U prvků pro zadání uživatelského jména a hesla vás mohou
zarazit jen tagy &lt;i:Interaction.Behaviors&gt; a atributy <em>jako behaviors:TextboxPasswordAttachedProperties.TextBoxChangedAction</em>,
jejichž význam vysvětlím za chvíli. Také vás hned  upozorním, že tlačítko “Přihlásit
se” je speciální tlačítko ((<em>&lt;controlex:ButtonEx</em>) dovolující reagovat na
stisknutí tlačítka uživatelem tak, že spustí metodu Execute objektu ICommand, což
standardní WP7 tlačítko nezvládá. Znovu  připomínám, že Silverlight ve WP7 je
bohužel založen na poměrně staré verzi 3 desktopového Silverlightu. Kód třídy ButtonEx
uvidíte také za chvíli.
</p>
        <p>
Máme view, ve view používáme “data binding”, ale nemáme ještě view modely, které fungují
pro view jako zdroj dat. 
</p>
        <p>
          <strong>V každém view modelu naší aplikace </strong>budeme používat objekt <em>IPosterousApplication</em> ke
komunikaci s Posterous, budeme chtít z view modelů navigovat na další view v aplikaci
a také bychom měli být schopni v každém view modelu získat  uživatelské jméno
a heslo zadané na na námi vytvářené přihlašovací obrazovce. To znamená, že společné
vlastnosti a služby view modelů pro naši aplikaci můžeme soustředit v bázové třídě
PosterousViewModelBase. Do projektové složky Views vložte novou třídu PosterousViewModelBase
a do ní zkopírujte následující kód. 
</p>
        <p>
PosterousViewModelBase je potomkem <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">naší
staré známé třídy ViewModelBase</a></p>
        <p>
          <script src="http://gist.github.com/793123.js">
          </script>
        </p>
        <p>
V konstruktoru třída PosterousViewModelBase přijímá odkaz na objekt <em>IPosterousApplication</em>,
který je základním rozcestnikem pro přístup k Posterous API, navigační službu <em>INavigationService</em>,
která view modelu dovolí navigovat na další view v aplikaci  (např. ze seznamu
článků na detail vybraného článku), a titulek zobrazené stránky.  <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">Titulek
převezme a nabízí poté ve vlastnosti PageTitle bázová třída ViewModelBase.</a></p>
        <p>
Navigační služba je představována rozhraním <em>INavigationService.</em></p>
        <p>
          <script src="http://gist.github.com/793126.js">
          </script>
        </p>
        <p>
Základní implementace rozhraní <em>INavigationService</em> pro WP7 je dostupná ve
třídě <em>DefaultWPNavigationService</em> a pouze obaluje navigační služby dostupné
v samotných WP7 aplikacích. 
</p>
        <script src="http://gist.github.com/793133.js">
        </script>
        <p>
Rozhraní <em>INavigationService</em> i třídu <em>DefaultWPNavigationService</em> vložte
do projektové složky HostServices.Více si o navigaci mezi různými view povíme v dalších
článcích.
</p>
        <p>
Vraťmě se k PosterousViewModelBase. V PosterousViewModelBase máme vždy uloženo ve
statických vlastnostech LastUsedUserName a LastUsedPassword poslední zadané přihlašovací
údaje, které může každý view model využít při získání nebo úpravě dat z Posterous. 
</p>
        <p>
          <em>Poznámka: Kdyby někoho z vás pohoršovali statické vlastnosti, klidně si jako domácí
úkol napište “CredentialsManager”, který bude injektován stejně jako již zmíněné dvě
další služby do view modelů. Prozatím nechci komplikovat kód víc, než je nutné.</em>
        </p>
        <p>
My máme dvě view, MainLoginView a LoginView, a proto vytvoříme i dva view modely.
Opět zdůrazňuju, že tato volba je na vás <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">a
díky “dědění view modelů”</a> bychom mohli ponechat třeba dvě view a vytvořit pro
ně jen jeden společný view model. 
</p>
        <p>
Do projektové složky ViewModels přidejte třídu nazvanou MainLoginViewModel – view
model pro MainLoginView. <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">Název
view modelu nyní musí odpovídat konvenci “NázevView +ViewModel”. Zdůrazňuju i zde,
že jde jen o konvenci a že si můžete jednoduše napsat jiný IViewModelResolver, který
dohledá dle vašich zcela jiných projektových konvencí k view vhodný view model.</a></p>
        <p>
MainLoginViewModel je sympaticky jednoduchý objekt. Má jen delegující konstruktor,
ve kterém předá své bázové třídě PosterousViewModelBase vyžadované povinné argumenty
posterousApplication, navigationService a titulek stránky. 
</p>
        <p>
          <script src="http://gist.github.com/793149.js">
          </script>
        </p>
        <p>
Texty v aplikaci nejsou prozatím lokalizovány a titulky stránek jsou uloženy ve třídě
GlobalConstants. Do “rootu” projektu přidejte třídu GlobalConstants.cs 
</p>
        <p>
          <script src="http://gist.github.com/793153.js">
          </script>
        </p>
        <p>
Název aplikace (APP_MAIN_TITLE) , podobně jako titulek stránky, <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">vydává
ve vlastnosti AppTitle  opět ViewModelBase</a></p>
        <p>
Jen o trochu složitější bude view model pro LoginView. Do projektové složky ViewModels
přidejte třídu LoginViewModel. 
</p>
        <p>
          <script src="http://gist.github.com/793171.js">
          </script>
        </p>
        <p>
V LoginViewModelu máme opět delegující konstruktor, jedinou změnou oproti MainLoginViewModelu
je to, že jako titulek stránky předáváme prázdný řetězec, protože předpokládáme, že
titulek na stránku dodá “nadřízené” view.
</p>
        <p>
Vlastnosti a jejich význam
</p>
        <table border="1" cellspacing="0" cellpadding="2" width="656">
          <tbody>
            <tr>
              <td valign="top" width="166">
                <strong>Název vlastnosti</strong>
              </td>
              <td valign="top" width="488">
                <strong>Popis</strong>
              </td>
            </tr>
            <tr>
              <td valign="top" width="170">
TextChangedAction</td>
              <td valign="top" width="484">
Akce, která má být vyvolána, když se ve view změní text přihlašovacího jména nebo
hesla. Tato akce je v konstruktoru inicializována tak, že si vynutíme opětovné vyhodnocení
toho, zda může být proveden LoginCommand. V článku popíšu, proč je to (prozatím?)
řešeno takto.</td>
            </tr>
            <tr>
              <td valign="top" width="170">
LoginCommand</td>
              <td valign="top" width="484">
Objekt podporující rozhraní ICommand,  který v metodě Execute zavolá metodu handleLogin.
Metoda handleLogin uloží zadané jméno a heslo do statických vlastností LastUsedPassword
a a LastUsedUserName a přesměruje uživatele na stránku se seznamem blogů. Instanční
vlastnost UserPassword je při každém pokusu o navigaci na stránku se seznamem blogů
“vyčištěna” tím, že je do ní uložen prázdný řetězec, a při návratu na přihlašovací
obrazovku tedy není automaticky předvyplněno heslo, což byl jeden z našich požadavků
na přihlašovací dialog.<br />
LoginCommand může být proveden jen tehdy, když bylo ve view zadáno a do view modelu
přes oboustranný (two way) binding zpropagováno uživatelské jméno a heslo. Pokud vlastnosti
UserName a UserPassword mají hodnotu null nebo obsahují prázdný řetězec, LoginCommand
nemůže být proveden.</td>
            </tr>
            <tr>
              <td valign="top" width="170">
UserName</td>
              <td valign="top" width="484">
Zadané přihlašovací jméno na službu Posterous. V <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">metodě
DoInternalInit, která je volána na začátku životního cyklu view modelu</a> předvyplníme
uživatelské jméno posledním zadaným uživatelským jménem, které jsme dříve uložili
do statické vlastnosti LastUsedUserName.</td>
            </tr>
            <tr>
              <td valign="top" width="170">
UserPassword</td>
              <td valign="top" width="484">
Heslo na službu Posterous.</td>
            </tr>
          </tbody>
        </table>
        <p>
Co potřebujeme, abychom mohli náš LoginViewModel zkompilovat? 
</p>
        <p>
Do třídy GlobalConstants přidejte URL dalšího view se seznamem blogů a článků. 
</p>
        <p>
          <script src="http://gist.github.com/793195.js">
          </script>
        </p>
        <p>
Stránku PostsListView.xaml vytvoříme v dalším článku, nyní ji celou vytvářet nemusíte.
Postačí do složky Views dát novou stránku (Page) s názvem PostsListView.xaml. 
</p>
        <p>
Jak jsem již psal, ve WP7 nemáme bohužel podporu pro objekty ICommand. Třída DelegateCommand,
jejíž instancí je LoginCommand, <strong>je minimalistickou implementací </strong>rozhraní
ICommand. 
</p>
        <p>
Pokud podobnou třídu nemáte, vložte si  do projektu třídu DelegateCommand. U
mě je v jmenném prostoru <strong>RStein.PosterousReader.Common.</strong></p>
        <p>
          <strong>
            <script src="http://gist.github.com/793206.js">
            </script>
          </strong>
        </p>
        <p>
Třídě DelegateCommand můžete předat dva delegáty. Delegát executeAction (“co má být
vykonáno”) je spuštěn v metodě Execute z rozhraní ICommand. Delegát canExecuteAction
představuje implementaci metody CanExecute (“může být  nyní command vykonán?”).
Minimalistická implementace je to proto, že nijak nepoužívám událost CanExecuteChanged,
a namísto toho jsem si pro “binding” vystavil speciální vlastnost CanExecuteCommand,
která v get akcesoru deleguje na metodu CanExecute.
</p>
        <p>
Vlastnost TextChangedAction v LoginViewModelu je delegát typu Action, který nám pomáhá
vyřešit jeden z požadavků na přihlášení. 
</p>
        <p>
          <em>“Jestliže není uživatelské jméno vyplněno (prázdný řetězec) a/nebo není vyplněno
heslo, tlačítko Přihlásit se je neaktivní.”</em>
        </p>
        <p>
To znamená, že potřebujeme po každém přidání nebo smazání znaku v textboxu pro zadání
jména uživatele i v textboxu pro zadání hesla zjišťovat, jestli můžeme ve view zpřístupnit
tlačítko pro přihlášení. Když je alespoň jeden textbox prázdný, tlačítko pro přihlášení
není dostupné, když je vyplněno alespoň jedním znakem jméno i heslo, tlačítko pro
přihlášení je dostupné.
</p>
        <p>
Jak je tento požadavek ve view a view modelu splněn?
</p>
        <p>
Ve view <em>LoginView</em> je vlastnost <em>IsEnabled</em> tlačítka “Přihlásit se“
z třídy <em>ButtonEx</em> “nabindována” na vlastnost <em>CanExecuteCommand</em> objektu <em>LoginCommand</em> ve
view modelu.
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_21.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_9.png" width="244" height="154" />
          </a>
        </p>
        <p>
Do projektové složky UI si přidejte třídu ButtonEx, která doplňuje standardní WP7
tlačítko o jednoduchou podporu objektů ICommand.
</p>
        <p>
          <strong>
            <script src="http://gist.github.com/793221.js">
            </script>
          </strong>
        </p>
        <p>
Vlastnost CanExecuteCommand musí vracet true, pokud je v každém textboxu alespoň jeden
znak, jinak false. Jak ale ve view modelu zjistíme, že uživatel zadal nebo smazal
v některém textovém poli další znak? Do view modelu se při oboustranném bindingu zpropaguje
hodnota z textového pole až po opuštění textového pole uživatelem, ale my přitom musíme
reagovat ve view modelu na zadání každého znaku.
</p>
        <p>
Takové chování textových polí ve WP7 skutečně nemáme a musíme si ho dopsat, a to nejlépe
za pomoci ”attached” vlastností a objektů <em>Behavior&lt;T&gt;</em>. Nejprve se podívejme,
jak vypadají objekty TextBox a PasswordBox v XAMLu, když jsou rozšířeny o “attached”
vlastnost <em>TextboxPasswordAttachedProperties.TextBoxChangedAction</em>, která je
“nabindována” na nám již známou vlastnost TextChangedAction typu Action ve view modelu. 
“Attached” vlastnost <em>TextBoxChangedAction</em> tedy říká: “Hej, kdykoli se změní
u prvku zadaný text, musí NĚKDO ochotný zavolat delegáta TextChangedAction, abychom
ve view modelu nebyli odříznuti od novinek ve světě view.”
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_23.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_10.png" width="244" height="154" />
          </a>
        </p>
        <p>
A ten někdo bude náš objekt Behavior , který zase světu sděluje: “Mám dobré vychování,
a když mi dovolíte vstoupit do bran tagu PasswordBox nebo TextBox, delegáta TextChangedAction
zavolám,  i když to sám WP7 TextBox a PasswordBox nezvládne.”
</p>
        <p>
          <script src="http://gist.github.com/793240.js">
          </script>
        </p>
        <p>
Další nepříjemností ve WP7 je, že i když objekt Behavior má mít pro TextBox a PasswordBox 
stejné chování, musíme napsat dva objekty Behavior pro každý prvek, protože TextBox
ani PasswordBox spolu kupodivu nemají moc společného. My se alespoň pokusíme kód v
obou objektech Behavior neduplikovat.
</p>
        <p>
 
</p>
        <p>
Do projektové složky Behaviors přidejte třídu TextboxPasswordAttachedProperties a
v ní vytvořte attached vlastnost TextBoxChangedAction.
</p>
        <p>
          <script src="http://gist.github.com/793248.js">
          </script>
        </p>
        <p>
Do složky Behaviors přidejte abstraktní třídu TextChangedBehaviorBase, která bude
fungovat jako základ pro dva podobné objekty Behavior určené pro TextBox (TextBoxTextChangedUpdateSourceBehavior)
a PasswordBox (PasswordTextChangedBehavior). <strong>Do projektu musíte přidat referenci
na knihovnu System.Windows.Interactivity, </strong>kterou naleznete většinou ve složce <em>c:\Program
Files\Microsoft SDKs\Expression\Blend\Windows Phone\v7.0\Libraries\System.Windows.Interactivity.dll. </em><strong>Bez
této knihovny není dostupná bázová třída Behavior&lt;T&gt;.</strong></p>
        <p>
          <script src="http://gist.github.com/793259.js">
          </script>
        </p>
        <p>
Metoda RunTextChangedAction se pro objekt Textbox a PasswordBox asociovaný s tímto
objektem Behavior  pokusí dohledat a spustit delegáta v “attached” vlastnost
TextBoxChangedAction. Metoda UpdateSource požádá odvozené třídy o vydání "objektu
BindingExpression” voláním metody GetBindingExpression. Vrácený objekt “BindingExpression“
by měl  zapouzdřovat propojení vlastnosti view modelu (např UserName) s textem
v textovém poli. Po kontrole, že se jedná o oboustranný (two way) binding, metoda
UpdateSource zavolá na objektu BindingExpression UpdateSource, což způsobí přenesení
hodnoty zadané uživatelem v textovém poli ve view do zdrojové vlastnosti (např. UserName)
ve view modelu.
</p>
        <p>
Potomek TextBoxTextChangedUpdateSourceBehavior v metodě GetBindingExpression vrátí
BindingExpression pro svou vlastnost Text. V přepsané metodě OnAttached, která je
volána vždy, když je objekt Behavior asociován s textboxem, si přihlásíme odběr události
TextChanged TextBoxu a při každé změně textu voláme zděděné a výše popsané metody
UpdateSource a RunTextChangedAction. V metodě OnDetaching si nezapomeneme odběr události
TextChanged odhlásit.
</p>
        <script src="http://gist.github.com/793285.js">
        </script>
        <p>
Pro PasswordBox máme dalšího potomka PasswordTextChangedBehavior, který se od třídy
TextBoxTextChangedUpdateSourceBehavior liší jen tím, že v metodě GetBindingExpression
vrací “BindingExpression” pro vlastnost Password a zadávaný text sleduje přes událost
PasswordChanged.
</p>
        <script src="https://gist.github.com/793557.js">
        </script>
        <p>
 
</p>
        <p>
V LoginView si nezapomeňte zkontrolovat, že máte namapovány správně xml prefixy <em>behaviors</em> a <em>i</em><strong></strong>na
správné jmenné prostory v C#, abyste mohli využívat novou attached vlastnost TextBoxChangedAction
a objekty TextBoxTextChangedUpdateSourceBehavior  a PasswordTextChangedBehavior.
</p>
        <p>
          <em>prostoryxmlns:behaviors="clr-namespace:RStein.PosterousReader.WP.Behaviors"<br />
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"</em>
        </p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_25.png">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_11.png" width="244" height="154" />
          </a>
        </p>
        <p>
Dodejme, že náš delegát TextChangedAction ve view modelu simuluje změnu objektu LoginCommand,
který je přidružen k tlačítku Přihlásit se a tlačítko Přihlásit tedy po každém zadání
znaku zjistí, jestli má být dostupné.  Zopakujme, že vlastnost IsEnabled tlačítka
je “nabindována” na vlastnost LoginCommand.CanExecuteCommand. 
</p>
        <p>
Aplikaci můžete spustit.
</p>
        <p>
          <em>Poznámka: Ještě si ale nezapomeňte do složky UIServices dát kód rozhraní IViewModelResolver
a třídy ViewModelResolver, které jsem popisoval v článku </em>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">
            <em>propojení
view modelu s view (stránkou)</em>
          </a>
          <em>, protože bez třídy ViewModelResolver by
aplikace nebyla schopna pro naše MainLoginView a LoginView dohledat právě vytvořené
view modely. A v aplikaci musíte mít samozřejmě všechny další třídy z předchozích
článků, které jsou odpovědné za “tombstoning” apod.</em>
        </p>
        <p>
U aplikace si můžete zkontrolovat, že:
</p>
        <ul>
          <li>
Přihlašovací dialog plní všechny požadavky, které jsme vypsal  na začátku článku.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png" /><br /><br /></li>
          <li>
Nemusíme se nijak starat o “tombstoning” aplikace. Zmáčkněte tlačítko Win, poté se
tlačítkem Back vraťte do aplikace a všechny hodnoty v textových polích zůstanou zachovány.<br /><br /></li>
          <li>
Tlačítko pro přihlášení je dostupné jen tehdy, když textová pole pro zadání jména
a hesla jsou vyplněna. Pokud alespoň jedno pole vyplněno není, tlačítko je neaktivní.<br /><br /></li>
          <li>
I naše minimalistická podpora rozhraní ICommand vede k tomu, že ve View nemáme žádný 
“code behind”. Logika stojící za view je jen ve view modelech a XAML tahá data z view
modelů přes “data binding”. Pokud přesně tohle to považujete za důležité, budete určitě
nadšeni. Jak uvidíte v dalších článcích, já jsem vůči strategii “vše do XAMLu” hodně
skeptický, ale XAML puristé <strike>si </strike>mohou jít po dnešku jistě <strike>ožrat
držku </strike>slavit<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png" />.<br /><br /></li>
          <li>
I když šlo jen o přihlašovací formulář, vytvořili jsme si další skládací kostky (attached
vlastnosti, Behavior, PosterousViewModelBase), které se nám budou hodit při psani
dalších view a view modelů (nejen)  v této aplikaci.<br /></li>
        </ul>
        <p>
Zauvažujte nad tím, jestli by se nám také nehodila nějaká podpora ve view modelech
pro ukládání nejen tranzientního stavu, ale i pro ukládání “trvalejšího” stavu, který
bude dostupný i v další nezávislé instanci aplikace. Možná by stálo za to, aby si
aplikace pamatovala poslední zadané přihlašovací jméno nejen při “tombstoningu”, ale
aby přihlašovací jméno bylo nabídnuto i při novém spuštění aplikace. A z hlediska
vývojáře  bezbolestná podpora pro ukládání perzistentního stavu (<a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">data
s “delší záruční lhůtou”</a>) bude námětem dalšího WP7 intermezza. Doufám, že se těšíte. <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png" /></p>
        <p>
          <strong>Předchozí články:<br /><br /></strong>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">Tipy
pro Windows Phone 7 aplikace I</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">Tipy
pro Windows Phone 7 aplikace III–propojení view modelu s view (stránkou)</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IV+Intermezzo+I+Zjednoduscaronenaacute+Registrace+Serializovatelnyacutech+T%c5%99iacuted+Nesouciacutech+Tranzientniacute+Stav+V+KnownTypesDictionary.aspx">Tipy
pro Windows Phone 7 aplikace IV - intermezzo I - zjednodušená registrace serializovatelných
tříd nesoucích tranzientní stav v KnownTypesDictionary</a>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=1ab0ecc7-7a79-4e17-b2f8-358bd7713695" />
      </body>
      <title>Tipy pro Windows Phone 7 aplikace V &amp;ndash; vytv&amp;aacute;ř&amp;iacute;me prvni aplikaci (a stav&amp;iacute;me ji na vytvořen&amp;yacute;ch z&amp;aacute;kladech)</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,1ab0ecc7-7a79-4e17-b2f8-358bd7713695.aspx</guid>
      <link>http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+V+Ndash+Vytvaacute%c5%99iacuteme+Prvni+Aplikaci+A+Staviacuteme+Ji+Na+Vytvo%c5%99enyacutech+Zaacutekladech.aspx</link>
      <pubDate>Mon, 24 Jan 2011 16:48:26 GMT</pubDate>
      <description>&lt;p&gt;
V &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;předchozích
článcích&lt;/a&gt; jsme si vytvořili miniframework pro &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;view
modely&lt;/a&gt;&amp;nbsp;&amp;nbsp; a ukázali si hostitele &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;našich
view modelů&lt;/a&gt;. Přišel čas naše znalosti, idiomy a návrhové vzory zakódované ve formě
aplikační infrastruktury v našem miniframeworku využít při tvorbě konkrétní aplikace.
Pro účely tohoto článku i následujících článků jsem se rozhodl, že vytvoříme aplikaci,
která nám dovolí spravovat vlastní blog na doméně &lt;a href="https://posterous.com/"&gt;Posterous&lt;/a&gt; s
využitím &lt;a href="http://posterousapi.codeplex.com/releases/view/55736#DownloadId=167194"&gt;Posterous
API&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Hlavní případy užití, které budeme v aplikaci podporovat.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Přihlášení uživatele ke svému účtu&amp;nbsp; - téma dnešního článku.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zobrazení seznamu blogů, které patří přihlášenému uživateli.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zobrazení seznamu příspěvků na vybraném blogu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zobrazení detailu příspěvku na blogu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Úprava stávajícího příspěvku na blogu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zadání nového příspěvku na blog.&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Jako vždy nás tato prozatím letmo načrtnutá témata dovedou k dalším podivným zákoutím
vývoje WP7 aplikací&amp;nbsp; a my se z nich s úsměvem záludnostmi WP7 &lt;strike&gt;poučeného
idiota&amp;nbsp; &lt;/strike&gt;zoceleného harcovníka pokusíme dostat.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png"&gt;.
&lt;/p&gt;
&lt;p&gt;
Skutečně vás nechci urážet popisem klikání ve Visual Studiu ani popisem základů XAMLu,
“data bindingu”, “behaviors”, takže jen napíšu, že byste před vytvářením aplikace
měli:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Stáhnout si a nainstalovat &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=04704acf-a63a-4f97-952c-8b51b34b00ce&amp;amp;displaylang=en"&gt;Windows
Phone Developer Tools.&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Ve Visual Studiu založte nový projekt Windows Phone Application – nejlepší bude, když
ho pojmenujete jako já &lt;em&gt;RStein.PosterousReader.WP&lt;/em&gt;, abyste nebyli zmateni názvy
jmenných prostorů dále v článku.&lt;br&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_1.png" width="244" height="170"&gt;&lt;/a&gt;
&lt;br&gt;
&amp;nbsp; 
&lt;li&gt;
Vývojářský život je na tomto projektu jednodušší o to, že k práci s Posterous API
použijeme můj &lt;a href="http://posterousapi.codeplex.com/releases/view/55736#DownloadId=167194"&gt;C#
Posterous API Wrapper pro WP7&lt;/a&gt;.&amp;nbsp; Po stažení přidejte referenci na knihovnu &lt;em&gt;RStein.Posterous.API.SLM &lt;/em&gt;do
svého projektu.&lt;br&gt;
A i když to dnes ještě není tak nutné, &lt;a href="https://posterous.com/"&gt;zřiďte si
na Posterous vlastní účet&lt;/a&gt;, abyste mohli aplikaci později testovat na reálných
datech. C# Posterous API pro nás v triádě Model-View-ViewModel bude představovat model,
což má pro nás výhodu, že se můžeme stále soustředit na view a view modely, o které
šlo i v předchozích článcích, a model můžeme považovat za černou skříňku.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
V novém projektu vytvořte hlavně dvě nové složky View a ViewModels. Na obrázku jsou
červeně podtrženy další složky, které si již dnes doporučuju přidat do projektu&amp;nbsp;
- Behaviors, Extensions, HostServices, Icons, SpecialTypes, UI, UIServices a hlavně
ViewModels a Views.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_2.png" width="94" height="244"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Předpokládám, že jste schopni do svého projektu vložit kód tříd, které jsem popisoval
v předchozích článcích. Seznam předchozích článků s výpisy kódu naleznete na konci
tohoto článku.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Dnes vytvoříme přihlašovací obrazovku do naší aplikace. Pro lepší představu je zde
obrazovka, kterou byste měli mít hotovou na konci dnešního článku.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://blog.renestein.net/content/binary/Windows-Live-Writer/C-Posterous-API-.3--s-podporou-i-pro-WP7_D37E/image_2.png" width="379" height="633"&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp; 
&lt;p&gt;
Nejprve určíme, které funkce musí obrazovka a její podkladový kód zvládat: 
&lt;ol&gt;
&lt;li&gt;
Přihlašovací obrazovka se zobrazí ihned po startu aplikace.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Uživateli dovolíme zadat přihlašovací jméno a heslo.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Jestliže není uživatelské jméno vyplněno (prázdný řetězec) a/nebo není vyplněno heslo,
tlačítko Přihlásit se je neaktivní.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Jestliže dojde k &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;“tombstoningu&lt;/a&gt;”
stránky, bude jméno i heslo po návratu z “tombstonovaného” stavu zachováno – ověříme
si tak poprvé in vivo, že &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;naše
třída ViewModelBase podporuje “tombstoning” přesně dle našich požadavků&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Po návratu na přihlašovací obrazovku z jiné části aplikace bude zachován jen obsah
textového pole “uživatelské jméno”, textové pole “heslo” bude prázdné.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Po kliknutí na tlačítko Přihlásit nebudeme zadané jméno a heslo ihned ověřovat, ale
uložíme oba údaje&amp;nbsp; pro použití na dalších stránkách aplikace. Poté přesměrujeme
uživatele na další stránku se seznamem blogů, kde bude jméno a heslo využito k získání
seznamu blogů uživatele. Důvodem je to, že v Posterous API se jméno a heslo zasílá
při každém webovém požadavku, žádné jednorázové přihlášení neexistuje a nemá smysl
generovat nějaký “dummy” požadavek jen pro ověření hesla. Jestliže se na stránce se
seznamem blogů, na kterou z přihlašovací obrazovky přesměrováváme, data kvůli neplatným
přihlašovacím údajům získat nepodaří, aplikace nás vrátí na přihlašovací obrazovku.
Vytvoření stránky se seznamem blogů bude téma dalšího článku.&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
A začínáme: 
&lt;p&gt;
Do složky Views vložte nové View pro přihlášení uživatele. V dialogu Add new item
vyberte Windows Phone Portrait Page a pojmenujte ji MainLoginView.xaml.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_9.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_3.png" width="244" height="170"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Jedná se o úvodní&amp;nbsp; stránku aplikace, a proto v deskriptoru WP7 aplikace nazvaném
WAMppManifest.xml, který naleznete v projektové složce Properties, změníme startovací
stránku na View/mainLoginView.xaml. &lt;script src="https://gist.github.com/793066.js"&gt; &lt;/script&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_13.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_5.png" width="244" height="154"&gt;&lt;/a&gt; 
&lt;p&gt;
I když to není u přihlašovacího dialogu nutné, v dnešním článku si ukážeme, jak můžeme
jednoduše složit jedno view z dalších nezávislých view a také to, že view nemusí být
jen stránka (Page), ale i “User Control”. Naše MainLoginView bude zobrazovat titulek
aplikace (Posterous klient), titulek stránky (Přihlášení) , ale textová pole “heslo”,
“uživatelské jméno” a tlačítko “Přihlásit" se” bude obsahovat “user control” LoginView,
který můžeme použít jako součást i zcela jiného view (stránky) v aplikaci.&amp;nbsp; Do
složky Views přidejte Windows Phone User Control a nazvěte jej LoginView.xaml. 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_15.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_6.png" width="244" height="170"&gt;&lt;/a&gt; 
&lt;p&gt;
Zkompilujte (Build) “solution”. 
&lt;p&gt;
Do view MainLoginView vložte tento kód: 
&lt;p&gt;
&lt;script src="http://gist.github.com/793080.js"&gt;&lt;/script&gt;
&lt;p&gt;
Jak jsem zmiňoval v &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;jednom
z předešlých článků&lt;/a&gt;, všechny stránky v aplikaci by měly být potomkem naší třídy &lt;a href="https://gist.github.com/763320"&gt;PageBase&lt;/a&gt;,
která je hostitelem pro view modely. Proto je naše stránka uzavřena v elementu &lt;em&gt;&amp;lt;controlex:PageBase&amp;gt;&lt;/em&gt;.&amp;nbsp;
XML jmenný prostor controleex je u mě namapován na xmlns:controlex="clr-namespace:RStein.PosterousReader.WP.UI".
V projektovém adresáři UI musíte mít tedy třídu PageBase.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_19.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_8.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Také v “code behind souboru” musíte třídu MainLoginView učinit potomkem PageBase.
&lt;/p&gt;
&lt;script src="https://gist.github.com/793085.js"&gt; &lt;/script&gt;
&lt;p&gt;
Hlavní xaml pro přihlášení uživatele obsahuje “User Control” LoginView, na který se
v MainLoginView odkazujeme. &lt;em&gt;(&amp;lt;views:LoginView Grid.Row="1"&amp;gt;&amp;lt;/views:LoginView&amp;gt;&lt;/em&gt;).&amp;nbsp;
XML jmenný prostor &lt;em&gt;views&lt;/em&gt; je mapován na jmenný prostor &lt;em&gt;RStein.PosterousReader.WP.Views &lt;/em&gt;v
C# (&lt;em&gt;xmlns:views="clr-namespace:RStein.PosterousReader.WP.Views&lt;/em&gt;) – v našem
případě tedy na projektový adresář Views.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_17.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_7.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Do view s názvem LoginView vložte následující XAML:
&lt;/p&gt;
&lt;script src="https://gist.github.com/793102.js"&gt; &lt;/script&gt;
&lt;p&gt;
Jak bylo vidět na snímku obrazovky na počátku článku, LoginView obsahuje hlavně textové
pole pro zadání jména uživatele (txtName) a prvek pro zadání hesla uživatele (txtPassword)
a tlačítko “Přihlásit se”. U prvků pro zadání uživatelského jména a hesla vás mohou
zarazit jen tagy &amp;lt;i:Interaction.Behaviors&amp;gt; a atributy &lt;em&gt;jako behaviors:TextboxPasswordAttachedProperties.TextBoxChangedAction&lt;/em&gt;,
jejichž význam vysvětlím za chvíli. Také vás hned&amp;nbsp; upozorním, že tlačítko “Přihlásit
se” je speciální tlačítko ((&lt;em&gt;&amp;lt;controlex:ButtonEx&lt;/em&gt;) dovolující reagovat na
stisknutí tlačítka uživatelem tak, že spustí metodu Execute objektu ICommand, což
standardní WP7 tlačítko nezvládá. Znovu&amp;nbsp; připomínám, že Silverlight ve WP7 je
bohužel založen na poměrně staré verzi 3 desktopového Silverlightu. Kód třídy ButtonEx
uvidíte také za chvíli.
&lt;/p&gt;
&lt;p&gt;
Máme view, ve view používáme “data binding”, ale nemáme ještě view modely, které fungují
pro view jako zdroj dat. 
&lt;p&gt;
&lt;strong&gt;V každém view modelu naší aplikace &lt;/strong&gt;budeme používat objekt &lt;em&gt;IPosterousApplication&lt;/em&gt; ke
komunikaci s Posterous, budeme chtít z view modelů navigovat na další view v aplikaci
a také bychom měli být schopni v každém view modelu získat&amp;nbsp; uživatelské jméno
a heslo zadané na na námi vytvářené přihlašovací obrazovce. To znamená, že společné
vlastnosti a služby view modelů pro naši aplikaci můžeme soustředit v bázové třídě
PosterousViewModelBase. Do projektové složky Views vložte novou třídu PosterousViewModelBase
a do ní zkopírujte následující kód. 
&lt;p&gt;
PosterousViewModelBase je potomkem &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;naší
staré známé třídy ViewModelBase&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/793123.js"&gt;&lt;/script&gt;
&lt;p&gt;
V konstruktoru třída PosterousViewModelBase přijímá odkaz na objekt &lt;em&gt;IPosterousApplication&lt;/em&gt;,
který je základním rozcestnikem pro přístup k Posterous API, navigační službu &lt;em&gt;INavigationService&lt;/em&gt;,
která view modelu dovolí navigovat na další view v aplikaci&amp;nbsp; (např. ze seznamu
článků na detail vybraného článku), a titulek zobrazené stránky.&amp;nbsp; &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;Titulek
převezme a nabízí poté ve vlastnosti PageTitle bázová třída ViewModelBase.&lt;/a&gt; 
&lt;p&gt;
Navigační služba je představována rozhraním &lt;em&gt;INavigationService.&lt;/em&gt; 
&lt;p&gt;
&lt;script src="http://gist.github.com/793126.js"&gt;&lt;/script&gt;
&lt;p&gt;
Základní implementace rozhraní &lt;em&gt;INavigationService&lt;/em&gt; pro WP7 je dostupná ve
třídě &lt;em&gt;DefaultWPNavigationService&lt;/em&gt; a pouze obaluje navigační služby dostupné
v samotných WP7 aplikacích. 
&lt;/p&gt;
&lt;script src="http://gist.github.com/793133.js"&gt;&lt;/script&gt;
&lt;p&gt;
Rozhraní &lt;em&gt;INavigationService&lt;/em&gt; i třídu &lt;em&gt;DefaultWPNavigationService&lt;/em&gt; vložte
do projektové složky HostServices.Více si o navigaci mezi různými view povíme v dalších
článcích.
&lt;/p&gt;
&lt;p&gt;
Vraťmě se k PosterousViewModelBase. V PosterousViewModelBase máme vždy uloženo ve
statických vlastnostech LastUsedUserName a LastUsedPassword poslední zadané přihlašovací
údaje, které může každý view model využít při získání nebo úpravě dat z Posterous. 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Poznámka: Kdyby někoho z vás pohoršovali statické vlastnosti, klidně si jako domácí
úkol napište “CredentialsManager”, který bude injektován stejně jako již zmíněné dvě
další služby do view modelů. Prozatím nechci komplikovat kód víc, než je nutné.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
My máme dvě view, MainLoginView a LoginView, a proto vytvoříme i dva view modely.
Opět zdůrazňuju, že tato volba je na vás &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;a
díky “dědění view modelů”&lt;/a&gt; bychom mohli ponechat třeba dvě view a vytvořit pro
ně jen jeden společný view model. 
&lt;p&gt;
Do projektové složky ViewModels přidejte třídu nazvanou MainLoginViewModel – view
model pro MainLoginView. &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;Název
view modelu nyní musí odpovídat konvenci “NázevView +ViewModel”. Zdůrazňuju i zde,
že jde jen o konvenci a že si můžete jednoduše napsat jiný IViewModelResolver, který
dohledá dle vašich zcela jiných projektových konvencí k view vhodný view model.&lt;/a&gt; 
&lt;p&gt;
MainLoginViewModel je sympaticky jednoduchý objekt. Má jen delegující konstruktor,
ve kterém předá své bázové třídě PosterousViewModelBase vyžadované povinné argumenty
posterousApplication, navigationService a titulek stránky. 
&lt;p&gt;
&lt;script src="http://gist.github.com/793149.js"&gt;&lt;/script&gt;
&lt;p&gt;
Texty v aplikaci nejsou prozatím lokalizovány a titulky stránek jsou uloženy ve třídě
GlobalConstants. Do “rootu” projektu přidejte třídu GlobalConstants.cs 
&lt;p&gt;
&lt;script src="http://gist.github.com/793153.js"&gt;&lt;/script&gt;
&lt;p&gt;
Název aplikace (APP_MAIN_TITLE) , podobně jako titulek stránky, &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;vydává
ve vlastnosti AppTitle&amp;nbsp; opět ViewModelBase&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Jen o trochu složitější bude view model pro LoginView. Do projektové složky ViewModels
přidejte třídu LoginViewModel. 
&lt;p&gt;
&lt;script src="http://gist.github.com/793171.js"&gt;&lt;/script&gt;
&lt;p&gt;
V LoginViewModelu máme opět delegující konstruktor, jedinou změnou oproti MainLoginViewModelu
je to, že jako titulek stránky předáváme prázdný řetězec, protože předpokládáme, že
titulek na stránku dodá “nadřízené” view.
&lt;/p&gt;
&lt;p&gt;
Vlastnosti a jejich význam
&lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="2" width="656"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="166"&gt;
&lt;strong&gt;Název vlastnosti&lt;/strong&gt;&lt;/td&gt;
&lt;td valign="top" width="488"&gt;
&lt;strong&gt;Popis&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="170"&gt;
TextChangedAction&lt;/td&gt;
&lt;td valign="top" width="484"&gt;
Akce, která má být vyvolána, když se ve view změní text přihlašovacího jména nebo
hesla. Tato akce je v konstruktoru inicializována tak, že si vynutíme opětovné vyhodnocení
toho, zda může být proveden LoginCommand. V článku popíšu, proč je to (prozatím?)
řešeno takto.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="170"&gt;
LoginCommand&lt;/td&gt;
&lt;td valign="top" width="484"&gt;
Objekt podporující rozhraní ICommand,&amp;nbsp; který v metodě Execute zavolá metodu handleLogin.
Metoda handleLogin uloží zadané jméno a heslo do statických vlastností LastUsedPassword
a a LastUsedUserName a přesměruje uživatele na stránku se seznamem blogů. Instanční
vlastnost UserPassword je při každém pokusu o navigaci na stránku se seznamem blogů
“vyčištěna” tím, že je do ní uložen prázdný řetězec, a při návratu na přihlašovací
obrazovku tedy není automaticky předvyplněno heslo, což byl jeden z našich požadavků
na přihlašovací dialog.&lt;br&gt;
LoginCommand může být proveden jen tehdy, když bylo ve view zadáno a do view modelu
přes oboustranný (two way) binding zpropagováno uživatelské jméno a heslo. Pokud vlastnosti
UserName a UserPassword mají hodnotu null nebo obsahují prázdný řetězec, LoginCommand
nemůže být proveden.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="170"&gt;
UserName&lt;/td&gt;
&lt;td valign="top" width="484"&gt;
Zadané přihlašovací jméno na službu Posterous. V &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;metodě
DoInternalInit, která je volána na začátku životního cyklu view modelu&lt;/a&gt; předvyplníme
uživatelské jméno posledním zadaným uživatelským jménem, které jsme dříve uložili
do statické vlastnosti LastUsedUserName.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="170"&gt;
UserPassword&lt;/td&gt;
&lt;td valign="top" width="484"&gt;
Heslo na službu Posterous.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Co potřebujeme, abychom mohli náš LoginViewModel zkompilovat? 
&lt;p&gt;
Do třídy GlobalConstants přidejte URL dalšího view se seznamem blogů a článků. 
&lt;p&gt;
&lt;script src="http://gist.github.com/793195.js"&gt;&lt;/script&gt;
&lt;p&gt;
Stránku PostsListView.xaml vytvoříme v dalším článku, nyní ji celou vytvářet nemusíte.
Postačí do složky Views dát novou stránku (Page) s názvem PostsListView.xaml. 
&lt;p&gt;
Jak jsem již psal, ve WP7 nemáme bohužel podporu pro objekty ICommand. Třída DelegateCommand,
jejíž instancí je LoginCommand, &lt;strong&gt;je minimalistickou implementací &lt;/strong&gt;rozhraní
ICommand. 
&lt;p&gt;
Pokud podobnou třídu nemáte, vložte si&amp;nbsp; do projektu třídu DelegateCommand. U
mě je v jmenném prostoru &lt;strong&gt;RStein.PosterousReader.Common.&lt;/strong&gt; 
&lt;p&gt;
&lt;strong&gt;&lt;script src="http://gist.github.com/793206.js"&gt;&lt;/script&gt;&lt;/strong&gt; 
&lt;p&gt;
Třídě DelegateCommand můžete předat dva delegáty. Delegát executeAction (“co má být
vykonáno”) je spuštěn v metodě Execute z rozhraní ICommand. Delegát canExecuteAction
představuje implementaci metody CanExecute (“může být&amp;nbsp; nyní command vykonán?”).
Minimalistická implementace je to proto, že nijak nepoužívám událost CanExecuteChanged,
a namísto toho jsem si pro “binding” vystavil speciální vlastnost CanExecuteCommand,
která v get akcesoru deleguje na metodu CanExecute.
&lt;/p&gt;
&lt;p&gt;
Vlastnost TextChangedAction v LoginViewModelu je delegát typu Action, který nám pomáhá
vyřešit jeden z požadavků na přihlášení. 
&lt;p&gt;
&lt;em&gt;“Jestliže není uživatelské jméno vyplněno (prázdný řetězec) a/nebo není vyplněno
heslo, tlačítko Přihlásit se je neaktivní.”&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
To znamená, že potřebujeme po každém přidání nebo smazání znaku v textboxu pro zadání
jména uživatele i v textboxu pro zadání hesla zjišťovat, jestli můžeme ve view zpřístupnit
tlačítko pro přihlášení. Když je alespoň jeden textbox prázdný, tlačítko pro přihlášení
není dostupné, když je vyplněno alespoň jedním znakem jméno i heslo, tlačítko pro
přihlášení je dostupné.
&lt;/p&gt;
&lt;p&gt;
Jak je tento požadavek ve view a view modelu splněn?
&lt;/p&gt;
&lt;p&gt;
Ve view &lt;em&gt;LoginView&lt;/em&gt; je vlastnost &lt;em&gt;IsEnabled&lt;/em&gt; tlačítka “Přihlásit se“
z třídy &lt;em&gt;ButtonEx&lt;/em&gt; “nabindována” na vlastnost &lt;em&gt;CanExecuteCommand&lt;/em&gt; objektu &lt;em&gt;LoginCommand&lt;/em&gt; ve
view modelu.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_21.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_9.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Do projektové složky UI si přidejte třídu ButtonEx, která doplňuje standardní WP7
tlačítko o jednoduchou podporu objektů ICommand.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;script src="http://gist.github.com/793221.js"&gt;&lt;/script&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Vlastnost CanExecuteCommand musí vracet true, pokud je v každém textboxu alespoň jeden
znak, jinak false. Jak ale ve view modelu zjistíme, že uživatel zadal nebo smazal
v některém textovém poli další znak? Do view modelu se při oboustranném bindingu zpropaguje
hodnota z textového pole až po opuštění textového pole uživatelem, ale my přitom musíme
reagovat ve view modelu na zadání každého znaku.
&lt;/p&gt;
&lt;p&gt;
Takové chování textových polí ve WP7 skutečně nemáme a musíme si ho dopsat, a to nejlépe
za pomoci ”attached” vlastností a objektů &lt;em&gt;Behavior&amp;lt;T&amp;gt;&lt;/em&gt;. Nejprve se podívejme,
jak vypadají objekty TextBox a PasswordBox v XAMLu, když jsou rozšířeny o “attached”
vlastnost &lt;em&gt;TextboxPasswordAttachedProperties.TextBoxChangedAction&lt;/em&gt;, která je
“nabindována” na nám již známou vlastnost TextChangedAction typu Action ve view modelu.&amp;nbsp;
“Attached” vlastnost &lt;em&gt;TextBoxChangedAction&lt;/em&gt; tedy říká: “Hej, kdykoli se změní
u prvku zadaný text, musí NĚKDO ochotný zavolat delegáta TextChangedAction, abychom
ve view modelu nebyli odříznuti od novinek ve světě view.”
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_23.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_10.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
A ten někdo bude náš objekt Behavior , který zase světu sděluje: “Mám dobré vychování,
a když mi dovolíte vstoupit do bran tagu PasswordBox nebo TextBox, delegáta TextChangedAction
zavolám,&amp;nbsp; i když to sám WP7 TextBox a PasswordBox nezvládne.”
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/793240.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Další nepříjemností ve WP7 je, že i když objekt Behavior má mít pro TextBox a PasswordBox&amp;nbsp;
stejné chování, musíme napsat dva objekty Behavior pro každý prvek, protože TextBox
ani PasswordBox spolu kupodivu nemají moc společného. My se alespoň pokusíme kód v
obou objektech Behavior neduplikovat.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Do projektové složky Behaviors přidejte třídu TextboxPasswordAttachedProperties a
v ní vytvořte attached vlastnost TextBoxChangedAction.
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/793248.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Do složky Behaviors přidejte abstraktní třídu TextChangedBehaviorBase, která bude
fungovat jako základ pro dva podobné objekty Behavior určené pro TextBox (TextBoxTextChangedUpdateSourceBehavior)
a PasswordBox (PasswordTextChangedBehavior). &lt;strong&gt;Do projektu musíte přidat referenci
na knihovnu System.Windows.Interactivity, &lt;/strong&gt;kterou naleznete většinou ve složce &lt;em&gt;c:\Program
Files\Microsoft SDKs\Expression\Blend\Windows Phone\v7.0\Libraries\System.Windows.Interactivity.dll. &lt;/em&gt;&lt;strong&gt;Bez
této knihovny není dostupná bázová třída Behavior&amp;lt;T&amp;gt;.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/793259.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Metoda RunTextChangedAction se pro objekt Textbox a PasswordBox asociovaný s tímto
objektem Behavior&amp;nbsp; pokusí dohledat a spustit delegáta v “attached” vlastnost
TextBoxChangedAction. Metoda UpdateSource požádá odvozené třídy o vydání "objektu
BindingExpression” voláním metody GetBindingExpression. Vrácený objekt “BindingExpression“
by měl&amp;nbsp; zapouzdřovat propojení vlastnosti view modelu (např UserName) s textem
v textovém poli. Po kontrole, že se jedná o oboustranný (two way) binding, metoda
UpdateSource zavolá na objektu BindingExpression UpdateSource, což způsobí přenesení
hodnoty zadané uživatelem v textovém poli ve view do zdrojové vlastnosti (např. UserName)
ve view modelu.
&lt;/p&gt;
&lt;p&gt;
Potomek TextBoxTextChangedUpdateSourceBehavior v metodě GetBindingExpression vrátí
BindingExpression pro svou vlastnost Text. V přepsané metodě OnAttached, která je
volána vždy, když je objekt Behavior asociován s textboxem, si přihlásíme odběr události
TextChanged TextBoxu a při každé změně textu voláme zděděné a výše popsané metody
UpdateSource a RunTextChangedAction. V metodě OnDetaching si nezapomeneme odběr události
TextChanged odhlásit.
&lt;/p&gt;
&lt;script src="http://gist.github.com/793285.js"&gt;&lt;/script&gt;
&lt;p&gt;
Pro PasswordBox máme dalšího potomka PasswordTextChangedBehavior, který se od třídy
TextBoxTextChangedUpdateSourceBehavior liší jen tím, že v metodě GetBindingExpression
vrací “BindingExpression” pro vlastnost Password a zadávaný text sleduje přes událost
PasswordChanged.
&lt;/p&gt;
&lt;script src="https://gist.github.com/793557.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
V LoginView si nezapomeňte zkontrolovat, že máte namapovány správně xml prefixy &lt;em&gt;behaviors&lt;/em&gt; a &lt;em&gt;i&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;na
správné jmenné prostory v C#, abyste mohli využívat novou attached vlastnost TextBoxChangedAction
a objekty TextBoxTextChangedUpdateSourceBehavior&amp;nbsp; a PasswordTextChangedBehavior.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;prostoryxmlns:behaviors="clr-namespace:RStein.PosterousReader.WP.Behaviors"&lt;br&gt;
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_25.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_11.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Dodejme, že náš delegát TextChangedAction ve view modelu simuluje změnu objektu LoginCommand,
který je přidružen k tlačítku Přihlásit se a tlačítko Přihlásit tedy po každém zadání
znaku zjistí, jestli má být dostupné.&amp;nbsp; Zopakujme, že vlastnost IsEnabled tlačítka
je “nabindována” na vlastnost LoginCommand.CanExecuteCommand. 
&lt;/p&gt;
&lt;p&gt;
Aplikaci můžete spustit.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Poznámka: Ještě si ale nezapomeňte do složky UIServices dát kód rozhraní IViewModelResolver
a třídy ViewModelResolver, které jsem popisoval v článku &lt;/em&gt;&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;&lt;em&gt;propojení
view modelu s view (stránkou)&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, protože bez třídy ViewModelResolver by
aplikace nebyla schopna pro naše MainLoginView a LoginView dohledat právě vytvořené
view modely. A v aplikaci musíte mít samozřejmě všechny další třídy z předchozích
článků, které jsou odpovědné za “tombstoning” apod.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
U aplikace si můžete zkontrolovat, že:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Přihlašovací dialog plní všechny požadavky, které jsme vypsal&amp;nbsp; na začátku článku.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Nemusíme se nijak starat o “tombstoning” aplikace. Zmáčkněte tlačítko Win, poté se
tlačítkem Back vraťte do aplikace a všechny hodnoty v textových polích zůstanou zachovány.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Tlačítko pro přihlášení je dostupné jen tehdy, když textová pole pro zadání jména
a hesla jsou vyplněna. Pokud alespoň jedno pole vyplněno není, tlačítko je neaktivní.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
I naše minimalistická podpora rozhraní ICommand vede k tomu, že ve View nemáme žádný&amp;nbsp;
“code behind”. Logika stojící za view je jen ve view modelech a XAML tahá data z view
modelů přes “data binding”. Pokud přesně tohle to považujete za důležité, budete určitě
nadšeni. Jak uvidíte v dalších článcích, já jsem vůči strategii “vše do XAMLu” hodně
skeptický, ale XAML puristé &lt;strike&gt;si &lt;/strike&gt;mohou jít po dnešku jistě &lt;strike&gt;ožrat
držku &lt;/strike&gt;slavit&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png"&gt;.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
I když šlo jen o přihlašovací formulář, vytvořili jsme si další skládací kostky (attached
vlastnosti, Behavior, PosterousViewModelBase), které se nám budou hodit při psani
dalších view a view modelů (nejen)&amp;nbsp; v této aplikaci.&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Zauvažujte nad tím, jestli by se nám také nehodila nějaká podpora ve view modelech
pro ukládání nejen tranzientního stavu, ale i pro ukládání “trvalejšího” stavu, který
bude dostupný i v další nezávislé instanci aplikace. Možná by stálo za to, aby si
aplikace pamatovala poslední zadané přihlašovací jméno nejen při “tombstoningu”, ale
aby přihlašovací jméno bylo nabídnuto i při novém spuštění aplikace. A z hlediska
vývojáře&amp;nbsp; bezbolestná podpora pro ukládání perzistentního stavu (&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;data
s “delší záruční lhůtou”&lt;/a&gt;) bude námětem dalšího WP7 intermezza. Doufám, že se těšíte. &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Předchozí články:&lt;br&gt;
&lt;br&gt;
&lt;/strong&gt;&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;Tipy
pro Windows Phone 7 aplikace I&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;Tipy
pro Windows Phone 7 aplikace III–propojení view modelu s view (stránkou)&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IV+Intermezzo+I+Zjednoduscaronenaacute+Registrace+Serializovatelnyacutech+T%c5%99iacuted+Nesouciacutech+Tranzientniacute+Stav+V+KnownTypesDictionary.aspx"&gt;Tipy
pro Windows Phone 7 aplikace IV - intermezzo I - zjednodušená registrace serializovatelných
tříd nesoucích tranzientní stav v KnownTypesDictionary&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=1ab0ecc7-7a79-4e17-b2f8-358bd7713695" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,1ab0ecc7-7a79-4e17-b2f8-358bd7713695.aspx</comments>
      <category>C# Posterous API</category>
      <category>Compact .Net Framework</category>
      <category>Návrhové vzory</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=0257bcba-1a86-4ec0-a779-e858ab369d9f</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,0257bcba-1a86-4ec0-a779-e858ab369d9f.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,0257bcba-1a86-4ec0-a779-e858ab369d9f.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=0257bcba-1a86-4ec0-a779-e858ab369d9f</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
 
</p>
        <p>
Dnešní článek je jen “intermezzem”, protože doplňuje <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">předchozí
článek</a> o slíbenou informaci, jak můžeme automaticky registrovat serializovatelné
třídy, jejichž instance  nesou tranzientní stav, který je uložen  v KnownTypesDictionary. <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">Přechozí
článek</a> končil <a href="https://gist.github.com/763469#file_known_types_dictionary.cs">ukázkou</a>,
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) <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx">DataContractSerializer</a>,
my se zaměříme v článku opět hlavně na řešení WP7 specialitek. 
</p>
        <p>
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 <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”</a>, i díl <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">třetí,
kde se bavíme o KnownTypesDctionary</a>.
</p>
        <p>
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.
</p>
        <p>
Když do KnownTypesDictionary ukládáme v jedné aplikaci instance z tříd OrderVO a InvoiceVO
a v jiné aplikaci instance TwitterPost a ObservableCollection&lt;TwitterPost &gt;,
musíme vždy znovu zmíněné třídy registrovat pomocí atributu <a href="http://msdn.microsoft.com/en-gb/library/system.runtime.serialization.knowntypeattribute.aspx">KnownType</a>.
</p>
        <p>
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 <em>GetKnownTypes</em>, jejíž název
je předán do konstruktoru atributu KnownType.
</p>
        <p>
 
</p>
        <p>
          <script src="https://gist.github.com/763469.js">
          </script>
Napevno zadrátované typy v <em>KnownTypesDctionary</em> 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.
</p>
        <p>
Místo abychom třídy v metodě <em>GetKnownTypes </em>registrovali přímo, delegujeme
odpovědnost za vrácení serializovatelných typů na specializovaného poskytovatele.<br /><em></em></p>
        <p>
          <em>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”.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows_9A1E/wlEmoticon-smile_2.png" /></em>
        </p>
        <p>
Poskytovatel je objekt podporující rozhraní IKnownTypeProvider s jednou samopopisnou
metodou.
</p>
        <p>
          <script src="http://gist.github.com/772649.js">
          </script>
        </p>
        <p>
Refaktorizujeme třídu KnownTypesDictionary, aby při vracení serializovatelných typů
využívala objekt IKnownTypeProvider. 
</p>
        <p>
          <script src="http://gist.github.com/772654.js">
          </script>
        </p>
        <p>
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. 
</p>
        <p>
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. 
</p>
        <p>
Jaké odpovědnosti bude mít DefaultKnownTypesProvider? 
</p>
        <ol>
          <li>
DefaultKnownTypesProvider nám vrátí všechny deskriptory třídy (Type) označené atributem
[DataContract] v hlavní assembly aplikace.<br /><br /></li>
          <li>
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.<br /><br /></li>
          <li>
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ů.<br /><br /></li>
          <li>
Pro všechny nalezené typy T zaregistruje i kolekci Observable&lt;T&gt;. 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&lt;OrderVO&gt;).<br /></li>
        </ol>
        <p>
Kód třídy DefaultKnownTypesProvider: 
</p>
        <p>
          <script src="http://gist.github.com/772673.js">
          </script>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. 
</p>
        <p>
          <script src="http://gist.github.com/772674.js">
          </script>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 <em>IAssemblyTypesProvider </em>nalezené v hlavní assembly.
</p>
        <p>
Chcete-li tedy automaticky vyhledat typy označené atributem <em>DataContract </em>v
další assembly, vložte do hlavní assembly třídu podporující rozhraní <em>IAssemblyTypesProvider<strong>.</strong></em></p>
        <script src="http://gist.github.com/772676.js">
        </script>
        <p>
Do proměnné <em>collectionTypes</em> v metodě <em>GetKnownTypes</em> 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&lt;T&gt;
v proměnné <em>types</em> balili znovu do kolekce ObservableCollection. Jinými slovy,
když v proměnné <em>types</em> bude kolekce <em>ObservableCollection&lt;OrderVO&gt;</em>,
do proměnné collectionTypes <strong>nebude </strong>generována kolekce <em>ObservableCollection&lt;ObservableCollection&lt;OrderVO&gt;&gt;</em>.
</p>
        <p>
          <script src="http://gist.github.com/772696.js">
          </script>
        </p>
        <p>
Na konci vracíme nalezené typy sloučené s vygenerovanými typy kolekcí ObservableCollection&lt;T&gt;
a dalšími a pro aplikaci specifickými typy z ostatnich poskytovatelů . Za poskytovatele
považujeme další objekty IKnownTypeProvider nalezené v hlavní assembly. <script src="http://gist.github.com/772704.js"></script></p>
        <p>
A tím máme hotovo. 
</p>
        <p>
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>
        <p>
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.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows_9A1E/wlEmoticon-smile_2.png" /></p>
        <p>
Předcházející články: 
</p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">Tipy
pro Windows Phone 7 aplikace I</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">Tipy
pro Windows Phone 7 aplikace III–propojení view modelu s view (stránkou)</a>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=0257bcba-1a86-4ec0-a779-e858ab369d9f" />
      </body>
      <title>Tipy pro Windows Phone 7 aplikace IV - intermezzo I - zjednodu&amp;scaron;en&amp;aacute; registrace serializovateln&amp;yacute;ch tř&amp;iacute;d nesouc&amp;iacute;ch tranzientn&amp;iacute; stav v KnownTypesDictionary</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,0257bcba-1a86-4ec0-a779-e858ab369d9f.aspx</guid>
      <link>http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IV+Intermezzo+I+Zjednoduscaronenaacute+Registrace+Serializovatelnyacutech+T%c5%99iacuted+Nesouciacutech+Tranzientniacute+Stav+V+KnownTypesDictionary.aspx</link>
      <pubDate>Mon, 10 Jan 2011 12:37:12 GMT</pubDate>
      <description>&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Dnešní článek je jen “intermezzem”, protože doplňuje &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;předchozí
článek&lt;/a&gt; o slíbenou informaci, jak můžeme automaticky registrovat serializovatelné
třídy, jejichž instance&amp;nbsp; nesou tranzientní stav, který je uložen&amp;nbsp; v KnownTypesDictionary. &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;Přechozí
článek&lt;/a&gt; končil &lt;a href="https://gist.github.com/763469#file_known_types_dictionary.cs"&gt;ukázkou&lt;/a&gt;,
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) &lt;a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx"&gt;DataContractSerializer&lt;/a&gt;,
my se zaměříme v článku opět hlavně na řešení WP7 specialitek. 
&lt;/p&gt;
&lt;p&gt;
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&amp;nbsp; tomuto intermezzu, pečlivě a pomalu si přečtěte jako předehru
k intermezzu &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”&lt;/a&gt;, i díl &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;třetí,
kde se bavíme o KnownTypesDctionary&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
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.
&lt;/p&gt;
&lt;p&gt;
Když do KnownTypesDictionary ukládáme v jedné aplikaci instance z tříd OrderVO a InvoiceVO
a v jiné aplikaci instance TwitterPost a ObservableCollection&amp;lt;TwitterPost &amp;gt;,
musíme vždy znovu zmíněné třídy registrovat pomocí atributu &lt;a href="http://msdn.microsoft.com/en-gb/library/system.runtime.serialization.knowntypeattribute.aspx"&gt;KnownType&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
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 &lt;em&gt;GetKnownTypes&lt;/em&gt;, jejíž název
je předán do konstruktoru atributu KnownType.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/763469.js"&gt; &lt;/script&gt;
Napevno zadrátované typy v &lt;em&gt;KnownTypesDctionary&lt;/em&gt; 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.
&lt;/p&gt;
&lt;p&gt;
Místo abychom třídy v metodě &lt;em&gt;GetKnownTypes &lt;/em&gt;registrovali přímo, delegujeme
odpovědnost za vrácení serializovatelných typů na specializovaného poskytovatele.&lt;br&gt;
&lt;em&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;BTW: To víte, že první a okouzlující zákon vztahu mezi třídami zní:&amp;nbsp; “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&amp;nbsp; také říká SRP – princip jedné odpovědnosti
třídy”.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows_9A1E/wlEmoticon-smile_2.png"&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Poskytovatel je objekt podporující rozhraní IKnownTypeProvider s jednou samopopisnou
metodou.
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/772649.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Refaktorizujeme třídu KnownTypesDictionary, aby při vracení serializovatelných typů
využívala objekt IKnownTypeProvider. 
&lt;p&gt;
&lt;script src="http://gist.github.com/772654.js"&gt;&lt;/script&gt;
&lt;p&gt;
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. 
&lt;p&gt;
Metoda GetKnownTypes vrátí všechny staticky registrované typy v poli KNOWN_TYPES společně
s&amp;nbsp; typy, které dodá&amp;nbsp; 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&amp;nbsp; 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. 
&lt;p&gt;
Jaké odpovědnosti bude mít DefaultKnownTypesProvider? 
&lt;ol&gt;
&lt;li&gt;
DefaultKnownTypesProvider nám vrátí všechny deskriptory třídy (Type) označené atributem
[DataContract] v hlavní assembly aplikace.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
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.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
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ů.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Pro všechny nalezené typy T zaregistruje i kolekci Observable&amp;lt;T&amp;gt;. 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&amp;lt;OrderVO&amp;gt;).&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Kód třídy DefaultKnownTypesProvider: 
&lt;p&gt;
&lt;script src="http://gist.github.com/772673.js"&gt;&lt;/script&gt;V metodě GetKnownTypes vyzvedneme
všechny typy z “hlavní”&amp;nbsp; (vstupní) assembly. Hlavní assembly získáme v metodě
getExecutingAssembly přes vlastnosti třídy Deployment. 
&lt;p&gt;
&lt;script src="http://gist.github.com/772674.js"&gt;&lt;/script&gt;Typy z hlavní&amp;nbsp; 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 &lt;em&gt;IAssemblyTypesProvider &lt;/em&gt;nalezené v hlavní assembly.
&lt;/p&gt;
&lt;p&gt;
Chcete-li tedy automaticky vyhledat typy označené atributem &lt;em&gt;DataContract &lt;/em&gt;v
další assembly, vložte do hlavní assembly třídu podporující rozhraní &lt;em&gt;IAssemblyTypesProvider&lt;strong&gt;.&lt;/strong&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;script src="http://gist.github.com/772676.js"&gt;&lt;/script&gt;
&lt;p&gt;
Do proměnné &lt;em&gt;collectionTypes&lt;/em&gt; v metodě &lt;em&gt;GetKnownTypes&lt;/em&gt; 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&amp;lt;T&amp;gt;
v proměnné &lt;em&gt;types&lt;/em&gt; balili znovu do kolekce ObservableCollection. Jinými slovy,
když v proměnné &lt;em&gt;types&lt;/em&gt; bude kolekce &lt;em&gt;ObservableCollection&amp;lt;OrderVO&amp;gt;&lt;/em&gt;,
do proměnné collectionTypes &lt;strong&gt;nebude &lt;/strong&gt;generována kolekce &lt;em&gt;ObservableCollection&amp;lt;ObservableCollection&amp;lt;OrderVO&amp;gt;&amp;gt;&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/772696.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Na konci vracíme nalezené typy sloučené s vygenerovanými typy kolekcí ObservableCollection&amp;lt;T&amp;gt;
a dalšími a pro aplikaci specifickými typy z ostatnich poskytovatelů . Za poskytovatele
považujeme další objekty IKnownTypeProvider nalezené v hlavní assembly. &lt;script src="http://gist.github.com/772704.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
A tím máme hotovo. 
&lt;p&gt;
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. 
&lt;p&gt;
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.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows_9A1E/wlEmoticon-smile_2.png"&gt; 
&lt;p&gt;
Předcházející články: 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;Tipy
pro Windows Phone 7 aplikace I&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;Tipy
pro Windows Phone 7 aplikace III–propojení view modelu s view (stránkou)&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=0257bcba-1a86-4ec0-a779-e858ab369d9f" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,0257bcba-1a86-4ec0-a779-e858ab369d9f.aspx</comments>
      <category>.NET Framework</category>
      <category>C#</category>
      <category>Návrhové vzory</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=38539832-2f1d-42cf-8549-b59697b093c4</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,38539832-2f1d-42cf-8549-b59697b093c4.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,38539832-2f1d-42cf-8549-b59697b093c4.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=38539832-2f1d-42cf-8549-b59697b093c4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>
            <font color="#ff0000">Update 4. 1.   2011  - upraven kód objektu
UIHelper a spolupracující metody tak, aby byl klíč generovaný pro tranzientní stav
každého view modelu skutečně unikátní.</font>
          </em>
          <font color="#ff0000">Když rozkliknete
GISTy, můžete se podívat i na původní verzi kódu.</font>
        </p>
        <p>
V <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">předchozím
článku</a> jsme se podrobně věnovali vytvoření bázové třídy pro view modely včetně
podpory ukládání tranzientního stavu během “tombstoningu” a na konci jsem slíbil,
že další díl bude věnován hlavně propojení našich view modelů s view. 
</p>
        <p>
View pro nás bude hostitel view modelu a v souladu s WP7 modelem navigace mezi jednotlivými
stránkami budeme za hlavního hostitele považovat potomka třídy <em>PhoneApplicationPage<strong>. </strong></em>Uvidíme
ale, že při vytváření View nejsme omezeni na potomky <em>PhoneApplicationPage, </em>protože
budeme schopni vytvořit i view jako potomka třídy <em>UserControl.</em></p>
        <p>
Zrekapitujme hlavní funkce, které by měl náš hostitel view modelů zvládat: 
</p>
        <ol>
          <li>
Při vytvoření stránky je třeba najít ke stránce přidružený view model. Dodejme již
nyní, že povinností hostitele bude dohledat i vnořené (dceřiné) view modely, jestliže
je jedna stránka složena z více nezávislých view a každé view může být asociováno
s jiným view modelem.<br /><br /></li>
          <li>
Při vytvoření stránky je nutné u view modelu volat metodu <em>Init</em> pro základní
inicializaci view modelu, jestliže view model podporuje naše rozhraní <em>IInittialize<strong>. </strong></em>Znovu
připomínám, co zaznělo v <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">minulém
článku</a>, že si implementaci žádných rozhraní u view modelů nevynucujeme.<br /><br /></li>
          <li>
Jestliže se stránka stane poprvé nebo po návratu uživatele “aktivní” (zobrazenou),
je nutné volat na view modelu metodu <em>Activate</em>, když view model podporuje
rozhraní <em>IActivated.<br /><br /></em>. 
</li>
          <li>
Jestliže uživatel ze stránky odchází, hostitel na view modelu volá metodu Deactivate
z rozhraní IDeactivated.<br /><br /></li>
          <li>
Hostitel musí být schopen při “tombstoningu” uložit tranzientní stav view modelu.<br /><br /></li>
          <li>
Po návratu z “tombstoningu” hostitel dovolí view modelu obnovit tranzientní stav.<br /><br /></li>
          <li>
            <strong>Hostitel se nás bude snažit ve view modelech odstínit od všech  WP7 nedomyšleností,
záludností, nesmyslných omezení a programátorských vrtochů, které jsou nedílnou a
z pohledu mobilní MS divize jistě i zábavnou součástí celkově kapriciozního životního
cyklu třídy PhoneApplicationPage.<br /></strong>
          </li>
        </ol>
        <p>
Nyní již můžeme přístoupit k vytvoření hostitele. Našim hostitelem bude třída <em>PageBase, </em>která
je potomkem PhoneApplicationPage z WP7 frameworku. Nakonec jsem pro účely článku zvolil
toto řešení, i když není problém v dalších dílech ukázat adaptér, který nás nutnosti
vlastní stránky v aplikaci odvozovat z bázové třídy <em>PageBase</em> zbaví. Myslím
si ale, že navigační model WP7 aplikací neposkytuje sám o sobě mnoho prostoru pro
kreativitu, a proto nutnost dědit z PageBase místo třídy PhoneApplicationPage z WP7
za nějak zvlášť restriktivní nepovažuju.
</p>
        <p>
Třída PageBase:
</p>
        <script src="https://gist.github.com/763320.js">
        </script>
        <p>
Kdykoli  dojde k aktivaci stránky, čímž míním první navigaci na stránku, nebo
návrat na stránku pomocí tlačítka Back, je volána metoda <em>OnNavigatedTo. </em>My
jsme přepsali metodu OnNavigatedTo a v ní vždy nastavíme svou vlastnost WasLayoutUpdateCalled
na false. <strong>Vlastnost WasLayoutUpdateCalled použijeme za chvíli, zde jen řekněme,
že tuto vlastnost potřebujeme k tomu, abychom poznali, že již je vytvořen celý vizuální
strom ovládacích prvků a že můžeme s ovládacími prvky bez obav pracovat. </strong>Bohužel
v metodě OnNavigatedTo vizuální strom prvků vytvořen být nemusí. O některých problémech,
které je nutné řešit, když není zcela vytvořen vizuální strom prvků, jsem již mluvil
u ovládacího prvku <em>WebBrowser </em>v <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">první
části tohoto seriálu</a>. 
</p>
        <p>
Metoda OnNavigatedTo také dá příkaz k vyzvednutí dříve uloženého tranzientního stavu
pomocí metody loadSavedTransientState z vlastnosti PhoneApplicationPage.State. Tranzientní
stav, pokud existuje, je pouze uložen do vlastnosti LastSavedTransientState a zatím
se s ním nijak nepracuje. Klíčem, pod kterým je uložen stav celé stránky včetně tranzientního
stavu view modelů, je plně kvalifikované jméno aktuální stránky (string stateKey =
GetType().FullName). <strong>Měli bychom si být vědomi, že při této implementaci nesmíme
mít jednu stránku v aplikaci nahranou vícekrát, protože by různé instance stejné stránky
mezi sebou sdílely stav. Když budete trvat na tom, že jedna stránka může mít v systému
několik instancí, není problém změnit generování klíče, pod kterým bude stav pro každou
unikátně identifikovanou instanci uložen.</strong></p>
        <script src="https://gist.github.com/763335.js">
        </script>
        <p>
Pokračujme v našem scénáři. V konstruktoru si přihlašujeme odběr události LayoutUpdated
(<em>LayoutUpdated += PageBase_LayoutUpdated;)<strong>, </strong></em>abychom byli
notifikováni, že již můžeme bezpečně pracovat s ovládacími prvky.
</p>
        <p>
 
</p>
        <p>
Obslužná metoda <em>handleLayoutUpdated</em> je po každé navigaci na stránku spouštěna 
jen jednou, a proto se podíváme na hodnotu vlastnosti  WasLayoutUpdateCalled
– jestliže má hodnotu true, nic dalšího neděláme. <strong>Jinak metoda zkontroluje,
zda instance PageBase je nově vytvořena, k čemuž dojde při první navigaci na stránku
a také po obnovení z “tombstonovaného" stavu. Jinak řečeno – když je volán konstruktor
třídy PageBase, znamená to, že máme stránku v “panenském” stavu, protože v ní nejsou
žádná data a dokonce ani nebyly připojeny view modely. A proto bezparametrický konstruktor
PageBase nastavuje vlastnost IsNewInstance na true, abychom v metodě <em>handleLayoutUpdated</em> 
věděli, že máme co do činění s novou instancí stránky. U nové stránky je třeba získat
view modely, a pokud je stránka obnovena po “tombstoningu”, je třeba do view modelů
nahrát tranzientní stav.  Při variantě “nová instance stránky” metoda <em>handleLayoutUpdated</em> volá
metodu LoadState.</strong></p>
        <p>
Jestliže nebyl volán konstruktor a stránka obsahuje veškerý stav, k čemuž většinou
dojde, když se vrátíme bez “tombstoningu” pomocí tlačítka Back na stránku, metoda <em>handleLayoutUpdated</em> volá
pouze pomocnou metodu <em>handleAllActivated, </em>která proiteruje všechny dříve
nahrané view modely, a když podporují rozhraní <em>IActivated</em>, tak na nich zavolá
metodu <em>Activate</em>.
</p>
        <script src="https://gist.github.com/763340.js">
        </script>
        <p>
Metoda <em>LoadState</em> ihned deleguje na metodu <em>restoreTransientState</em>,
jíž předá v objektu ElementIndexPair odkaz na aktuální stránku (this), která představuje
“root” všech prvků, a relativní index nastavený na 0 (první prvek na této úrovni).
V dalším argumentu jako prvek, pro který má být obnoven stav, předá opět odkaz na
aktuální stránku (this) a poslední argument, ve kterém metoda <em>restoreTransientState</em> očekává
naposledy použitý view model, je null, protože se žádnými view modely se ještě nepracuje.
</p>
        <p>
Metoda <em>restoreTransientState</em> nejprve zkontroluje, jestli předaný ovládací
prvek představuje View. K tomu použije objekt podporující rozhraní IViewModelResolver,
který je uložen ve statické vlastnosti ViewModelManager. Přesněji řečeno, ve vlastnosti
ViewModelManager můžete uložit delegáta (<em>Func<iviewmodelresolver>
)
</iviewmodelresolver></em>, který vrací objekt realizující rozhraní IViewModelResolver.
Ve statickém konstruktoru třídy PageBase ukládám do vlastnosti ViewModelManager funkci,
která vytváří v mé aplikaci výchozí IViewModelResolver s názvem ViewModelResolver
(<em>ViewModelManager = () =&gt; new ViewModelResolver();)</em></p>
        <p>
Rozhraní IViewModelResolver
</p>
        <p>
          <script src="https://gist.github.com/763365.js">
          </script>
        </p>
        <p>
Metodě IsView předáte vybraný objekt a ona vám vrátí true, jestliže objekt považuje
za view, pro které by měl existovat view model. Metoda ResolveViewModel přijme objekt
představující view a dohledá k němu view model.
</p>
        <p>
Pro lepší představu vám mohu bez podrobnějšího komentáře ukázat třídu, která v aplikaci
používající Posterous API dohledá k view view model na základě jmenné konvence. Za
View se považuje každá instance z třídy, jejíž název končí znaky “View”, a k tomuto
View je vrácen view model, který se jmenuje stejně jako view, ale končí znaky “ViewModel”.
K view s názvem Login<em>View </em>je tedy vrácen view model s názvem Login<em>ViewModel.</em></p>
        <script src="https://gist.github.com/763375.js">
        </script>
        <p>
Vraťme se k metodě restoreTransientState. Když metoda zjistí, že objekt představuje
view, pokusí se dohledat dříve uložený tranzientní stav. Stav je uložen pro každé
view v objektu IDictionary, konkrétně v třídě KnownTypesDictionary, pod klíčem, kterým
je úplné jméno ovládacího prvku – úplným jménem se rozumí jméno třídy ovládacího prvku
+ jména tříd všech jeho vizuálních předků (<em>ancestors</em>). Ke jménu třídy každého
prvku je přidán pořadový indexu prvku mezi prvky na stejné úrovni vizuálního stromu.
Klíč generuje třída UIHelper v metodě GetTransientStateKey.
</p>
        <p>
          <script src="https://gist.github.com/763381.js">
          </script>
Metoda restoreTransientState se poté s s využitím metody prepareViewModel pokusí získat
přes ViewModelManager view model (<em>ViewModelManager().ResolveViewModel(obj</em>),
dále zjistí, jestli view model podporuje rozhraní ITransientStateManager, IInitialize
a a IActivated a pokračuje takto:
</p>
        <ol>
          <li>
Jestliže máme uložen tranzientní stav (došlo k “tombstoningu”) a view model podporuje
rozhraní ITransientStateManager, zavoláme metodu LoadState z rozhraní ITransientStateManager
(<em>stateManager.LoadState(LastSavedTransientState[stateKey]); </em>a view model
tak dostane šanci načíst dříve uložená tranzientní data.<br /><br /></li>
          <li>
Když nemáme uložen tranzientní stav a view model podporuje rozhraní IInitialize, zavoláme
metodu IInitialize.Init. View model tak dostane šanci nahrát data, ať už se souboru,
z webové služby nebo jiného datového zdroje, která mají být zobrazena v aktuálním
view.<br /></li>
        </ol>
        <p>
Poté, co view model obnoví nebo inicializuje svůj stav, je volána metoda activateAndSetDataContext,
která na view modelech podporujících rozhraní IActivated zavolá metodu Activate a
nastaví view model jako datový zdroj (“DataContext”) view.
</p>
        <p>
Nakonec pro všechny dceřiné prvky, které mohou představovat vnořená view (např. user
control), rekurzivně zavoláme opět metodu restoreTransientState. K získání dceřiných
prvků a jejich relativního indexu mezi prvky na stejné úrovni zanoření ve vizuálním
stromu je použita metoda UIHelper.GetChildren.
</p>
        <script src="https://gist.github.com/763405.js">
        </script>
        <p>
Metoda LoadState, restoreTransientState a další pomocné metody, o kterých jsme mluvili
v předchozích odstavcích:
</p>
        <script src="https://gist.github.com/763410.js">
        </script>
        <p>
Za povšimnutí stojí ve scénáři metody restoreTransientState ještě několik dalších
věcí:
</p>
        <ul>
          <li>
Když zjišťujeme, jestli objekt podporuje rozhraní IInitialize (metoda <em>getInitObjectWithSyncContext</em>),
ihned do view modelu zpropagujeme synchronizační kontext (<em>initObject.SynchContext
= SynchronizationContext.Current</em>;), aby například událost PropertyChanged mohla
být vyvolávána vždy v UI vláknu.<br /><br /></li>
          <li>
Pomocná metoda <em>selectViewModel(frameworkElement, lastViewModel, currentViewModel);</em> odpovědná
za výběr view modelu zajistí, že když IViewModelResolver nenalezne pro view žádný
view model, automaticky view přiřadí view model použitý u předchozího view. Kdy to
potřebujete? Třeba když stránku rozdělíte na několik nezávislých “user controls”,
tak se můžete rozhodnout, jestli bude mít každý user control (view) svůj view model,
nebo view model vytvoříte jen pro celou stránku a “user controls” view modely automaticky
“zdědí”. To byl jen jeden příklad - úroveň zanoření view je zcela ve vaší režii. Slovo
“zdědí” je v uvozovkách, protože nejde o klasické dědení DataContextu, ale k předání
posledně použitého view modelu dojde i tehdy, když dvě view nemají společné “nadview”.<br /></li>
        </ul>
        <p>
          <em>Poznámka: Nejprve jsem chtěl volání metod Init a LoadState na view modelech a
následné nastavení DataContextu u view dát do jiného vlákna. Problém je v tomto případě
s dědením view modelů. Když přiřadíte view model, na kterém jste zavolali asynchronně
metodu Init, dalšímu vnořenému View, tak se může stát, že metoda Init ještě nedoběhla,
view model u prvního view nastaven není, ale u vnořeného (druhého) view již nastaven
je, což může vést k podivným a kvůli použití více vláken obtížně reprodukovatelným
chybám. Za asynchronní zpracování časově náročných scénářů zodpovídají samotné view
modely, které by měly přepisovat virtuální metodu DoInternalAsyncInit z ViewModelBase.
Metodu DoInternalAsyncInit jsem <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">popisoval
v předchozím článku</a>.</em>
        </p>
        <p>
Viděli jsme, kdy hostitel volá metody Init, Activate a kdy voláním metody LoadState
obnoví tranzientní stav ve view modelech. Ještě nám zbývá projít, kdy ukládáme tranzientní
stav a kdy notifikujeme view modely voláním jejich metody Deactivate o tom, že k nim
přidružené view (stránka) není již aktivní.
</p>
        <p>
          <strong>Nebudeme při ukládání tranzientního stavu nijak pátrat, jestli došlo k “tombstoningu”,
ale stav view modelů do <em>PhoneApplicationPage.State</em> uložíme vždy, když dojde
k opuštění stránky. Hlavním důsledkem tohoto rozhodnutí je, že s obsluhou metod 
Application_Launching, Application_Activated, Application_Deactivated a Application_Closing,
kterou jsem popisoval minule, se nemusíte kvůli “tombstoningu” trápit a zmíněné metody
můžete většinou zcela ignorovat.</strong>
        </p>
        <p>
O opuštění stránky jsm informováni v metodě OnNavigatedFrom, kterou přepíšeme. Metoda
OnNavigatedFrom voláním metody SaveState uloží stav všech view modelů a poté metoda
handleAllDeactivated na všech modelech  podporujících rozhraní IDeactivated zavolá
metodu Deactivate.
</p>
        <script src="https://gist.github.com/763441.js">
        </script>
        <p>
Popisovat kompletně logiku v metodě SaveState nemá smysl, protože tato metoda je reverzní
k metodě LoadState. Pro všechny view rekurzivně vyhledá jejich view modely a dovolí
jim uložit pod unikátním klíčem view, který je vygenerován třídou UIHelper, tranzientní
stav. Ten samý tranzientní stav view modelů, jehož obnovení v metodě LoadState jsem
popisoval výše.  <script src="https://gist.github.com/763445.js"></script></p>
        <p>
Za komentář stojí, že podmínka if<em> (stateManager != null &amp;&amp; stateManager
!= lastDataContext) </em>ošetřuje, abychom neukládali trazientní stav view modelu,
který slouží jako DataContext u více View, opakovaně, ale vždy pouze jednou.
</p>
        <p>
Tranzientní stav všech view modelů je ukládán do speciálního objektu Dictionary s
názvem KnownTypesDictionary.
</p>
        <p>
          <em>var statebag = new KnownTypesDictionary();</em>
        </p>
        <p>
Připomínám, že při tombstoningu je možné uložit jen serializovatelné objekty. Představme
si nyní, že KnownTypesDictionary je potomek třídy  Dictionary&lt;string, object&gt;.
Do takového objektu Dictionary můžeme vložit kteroukoli instanci z třídy, která je
přímo či nepřimo potomkem třídy Object, ale při pokusu o serializaci dostaneme chybu,
protože naše potomky DataContractSerializer nezná a očekává, že v kolekci budou jen
instance třídy Object, a ne instance odvozených tříd. Pomocí atributu <a href="http://msdn.microsoft.com/en-gb/library/system.runtime.serialization.knowntypeattribute.aspx">KnownType</a>,
který je aplikován na KnownTypesDictionary, můžeme DataContractSerializer informovat,
které všechny třídy má v objektu Dictionary očekávat. Jednou z  možností, jak
to udělat, je předat atributu KnownType název statické metody, která seznam “známých”
tříd vrací. 
</p>
        <p>
Dnes si ukážeme jednoduchou verzi třídy  <em>KnownTypesDictionary</em>, která
v metodě GetKnownTypes vrátí fixní seznam "známých” tříd. Příště si ukážeme, jak budou
“známé” třídy dohledány a registrovány  automaticky bez nutnosti vytvářet seznam
známých tříd vždy znovu a “natvrdo” v každé aplikaci. V dalších dílech také zjistíme,
jak právě vytvořená infrastruktura nám dovolí vytvářet WP7 aplikace příslovečným lusknutím
prstu, tedy spíš nečetným lusknutím prstů o klávesnici. <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/8b4a80e9bf58_926F/wlEmoticon-smile_2.png" /><script src="https://gist.github.com/763469.js"></script></p>
        <p>
.
</p>
        <p>
 
</p>
        <p>
Předcházející články: 
</p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">Tipy
pro Windows Phone 7 aplikace I</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”</a>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=38539832-2f1d-42cf-8549-b59697b093c4" />
      </body>
      <title>Tipy pro Windows Phone 7 aplikace III&amp;ndash;propojen&amp;iacute; view modelu s view (str&amp;aacute;nkou)</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,38539832-2f1d-42cf-8549-b59697b093c4.aspx</guid>
      <link>http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx</link>
      <pubDate>Mon, 03 Jan 2011 14:46:50 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;&lt;font color="#ff0000"&gt;Update 4. 1.&amp;nbsp;&amp;nbsp; 2011&amp;nbsp; - upraven kód objektu
UIHelper a spolupracující metody tak, aby byl klíč generovaný pro tranzientní stav
každého view modelu skutečně unikátní.&lt;/font&gt;&lt;/em&gt; &lt;font color="#ff0000"&gt;Když rozkliknete
GISTy, můžete se podívat i na původní verzi kódu.&lt;/font&gt; 
&lt;p&gt;
V &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;předchozím
článku&lt;/a&gt; jsme se podrobně věnovali vytvoření bázové třídy pro view modely včetně
podpory ukládání tranzientního stavu během “tombstoningu” a na konci jsem slíbil,
že další díl bude věnován hlavně propojení našich view modelů s view. 
&lt;p&gt;
View pro nás bude hostitel view modelu a v souladu s WP7 modelem navigace mezi jednotlivými
stránkami budeme za hlavního hostitele považovat potomka třídy &lt;em&gt;PhoneApplicationPage&lt;strong&gt;. &lt;/strong&gt;&lt;/em&gt;Uvidíme
ale, že při vytváření View nejsme omezeni na potomky &lt;em&gt;PhoneApplicationPage, &lt;/em&gt;protože
budeme schopni vytvořit i view jako potomka třídy &lt;em&gt;UserControl.&lt;/em&gt; 
&lt;p&gt;
Zrekapitujme hlavní funkce, které by měl náš hostitel view modelů zvládat: 
&lt;ol&gt;
&lt;li&gt;
Při vytvoření stránky je třeba najít ke stránce přidružený view model. Dodejme již
nyní, že povinností hostitele bude dohledat i vnořené (dceřiné) view modely, jestliže
je jedna stránka složena z více nezávislých view a každé view může být asociováno
s jiným view modelem.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Při vytvoření stránky je nutné u view modelu volat metodu &lt;em&gt;Init&lt;/em&gt; pro základní
inicializaci view modelu, jestliže view model podporuje naše rozhraní &lt;em&gt;IInittialize&lt;strong&gt;. &lt;/strong&gt;&lt;/em&gt;Znovu
připomínám, co zaznělo v &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;minulém
článku&lt;/a&gt;, že si implementaci žádných rozhraní u view modelů nevynucujeme.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Jestliže se stránka stane poprvé nebo po návratu uživatele “aktivní” (zobrazenou),
je nutné volat na view modelu metodu &lt;em&gt;Activate&lt;/em&gt;, když view model podporuje
rozhraní &lt;em&gt;IActivated.&lt;br&gt;
&lt;br&gt;
&lt;/em&gt;. 
&lt;li&gt;
Jestliže uživatel ze stránky odchází, hostitel na view modelu volá metodu Deactivate
z rozhraní IDeactivated.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Hostitel musí být schopen při “tombstoningu” uložit tranzientní stav view modelu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Po návratu z “tombstoningu” hostitel dovolí view modelu obnovit tranzientní stav.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
&lt;strong&gt;Hostitel se nás bude snažit ve view modelech odstínit od všech&amp;nbsp; WP7 nedomyšleností,
záludností, nesmyslných omezení a programátorských vrtochů, které jsou nedílnou a
z pohledu mobilní MS divize jistě i zábavnou součástí celkově kapriciozního životního
cyklu třídy PhoneApplicationPage.&lt;br&gt;
&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Nyní již můžeme přístoupit k vytvoření hostitele. Našim hostitelem bude třída &lt;em&gt;PageBase, &lt;/em&gt;která
je potomkem PhoneApplicationPage z WP7 frameworku. Nakonec jsem pro účely článku zvolil
toto řešení, i když není problém v dalších dílech ukázat adaptér, který nás nutnosti
vlastní stránky v aplikaci odvozovat z bázové třídy &lt;em&gt;PageBase&lt;/em&gt; zbaví. Myslím
si ale, že navigační model WP7 aplikací neposkytuje sám o sobě mnoho prostoru pro
kreativitu, a proto nutnost dědit z PageBase místo třídy PhoneApplicationPage z WP7
za nějak zvlášť restriktivní nepovažuju.
&lt;/p&gt;
&lt;p&gt;
Třída PageBase:
&lt;/p&gt;
&lt;script src="https://gist.github.com/763320.js"&gt; &lt;/script&gt;
&lt;p&gt;
Kdykoli&amp;nbsp; dojde k aktivaci stránky, čímž míním první navigaci na stránku, nebo
návrat na stránku pomocí tlačítka Back, je volána metoda &lt;em&gt;OnNavigatedTo. &lt;/em&gt;My
jsme přepsali metodu OnNavigatedTo a v ní vždy nastavíme svou vlastnost WasLayoutUpdateCalled
na false. &lt;strong&gt;Vlastnost WasLayoutUpdateCalled použijeme za chvíli, zde jen řekněme,
že tuto vlastnost potřebujeme k tomu, abychom poznali, že již je vytvořen celý vizuální
strom ovládacích prvků a že můžeme s ovládacími prvky bez obav pracovat. &lt;/strong&gt;Bohužel
v metodě OnNavigatedTo vizuální strom prvků vytvořen být nemusí. O některých problémech,
které je nutné řešit, když není zcela vytvořen vizuální strom prvků, jsem již mluvil
u ovládacího prvku &lt;em&gt;WebBrowser &lt;/em&gt;v &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;první
části tohoto seriálu&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
Metoda OnNavigatedTo také dá příkaz k vyzvednutí dříve uloženého tranzientního stavu
pomocí metody loadSavedTransientState z vlastnosti PhoneApplicationPage.State. Tranzientní
stav, pokud existuje, je pouze uložen do vlastnosti LastSavedTransientState a zatím
se s ním nijak nepracuje. Klíčem, pod kterým je uložen stav celé stránky včetně tranzientního
stavu view modelů, je plně kvalifikované jméno aktuální stránky (string stateKey =
GetType().FullName). &lt;strong&gt;Měli bychom si být vědomi, že při této implementaci nesmíme
mít jednu stránku v aplikaci nahranou vícekrát, protože by různé instance stejné stránky
mezi sebou sdílely stav. Když budete trvat na tom, že jedna stránka může mít v systému
několik instancí, není problém změnit generování klíče, pod kterým bude stav pro každou
unikátně identifikovanou instanci uložen.&lt;/strong&gt;
&lt;/p&gt;
&lt;script src="https://gist.github.com/763335.js"&gt; &lt;/script&gt;
&lt;p&gt;
Pokračujme v našem scénáři. V konstruktoru si přihlašujeme odběr události LayoutUpdated
(&lt;em&gt;LayoutUpdated += PageBase_LayoutUpdated;)&lt;strong&gt;, &lt;/strong&gt;&lt;/em&gt;abychom byli
notifikováni, že již můžeme bezpečně pracovat s ovládacími prvky.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Obslužná metoda &lt;em&gt;handleLayoutUpdated&lt;/em&gt; je po každé navigaci na stránku spouštěna&amp;nbsp;
jen jednou, a proto se podíváme na hodnotu vlastnosti&amp;nbsp; WasLayoutUpdateCalled
– jestliže má hodnotu true, nic dalšího neděláme. &lt;strong&gt;Jinak metoda zkontroluje,
zda instance PageBase je nově vytvořena, k čemuž dojde při první navigaci na stránku
a také po obnovení z “tombstonovaného" stavu. Jinak řečeno – když je volán konstruktor
třídy PageBase, znamená to, že máme stránku v “panenském” stavu, protože v ní nejsou
žádná data a dokonce ani nebyly připojeny view modely. A proto bezparametrický konstruktor
PageBase nastavuje vlastnost IsNewInstance na true, abychom v metodě &lt;em&gt;handleLayoutUpdated&lt;/em&gt;&amp;nbsp;
věděli, že máme co do činění s novou instancí stránky. U nové stránky je třeba získat
view modely, a pokud je stránka obnovena po “tombstoningu”, je třeba do view modelů
nahrát tranzientní stav.&amp;nbsp; Při variantě “nová instance stránky” metoda &lt;em&gt;handleLayoutUpdated&lt;/em&gt; volá
metodu LoadState.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Jestliže nebyl volán konstruktor a stránka obsahuje veškerý stav, k čemuž většinou
dojde, když se vrátíme bez “tombstoningu” pomocí tlačítka Back na stránku, metoda &lt;em&gt;handleLayoutUpdated&lt;/em&gt; volá
pouze pomocnou metodu &lt;em&gt;handleAllActivated, &lt;/em&gt;která proiteruje všechny dříve
nahrané view modely, a když podporují rozhraní &lt;em&gt;IActivated&lt;/em&gt;, tak na nich zavolá
metodu &lt;em&gt;Activate&lt;/em&gt;.
&lt;/p&gt;
&lt;script src="https://gist.github.com/763340.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metoda &lt;em&gt;LoadState&lt;/em&gt; ihned deleguje na metodu &lt;em&gt;restoreTransientState&lt;/em&gt;,
jíž předá v objektu ElementIndexPair odkaz na aktuální stránku (this), která představuje
“root” všech prvků, a relativní index nastavený na 0 (první prvek na této úrovni).
V dalším argumentu jako prvek, pro který má být obnoven stav, předá opět odkaz na
aktuální stránku (this) a poslední argument, ve kterém metoda &lt;em&gt;restoreTransientState&lt;/em&gt; očekává
naposledy použitý view model, je null, protože se žádnými view modely se ještě nepracuje.
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;restoreTransientState&lt;/em&gt; nejprve zkontroluje, jestli předaný ovládací
prvek představuje View. K tomu použije objekt podporující rozhraní IViewModelResolver,
který je uložen ve statické vlastnosti ViewModelManager. Přesněji řečeno, ve vlastnosti
ViewModelManager můžete uložit delegáta (&lt;em&gt;Func&lt;iviewmodelresolver&gt;
)
&lt;/em&gt;, který vrací objekt realizující rozhraní IViewModelResolver. Ve statickém konstruktoru
třídy PageBase ukládám do vlastnosti ViewModelManager funkci, která vytváří v mé aplikaci
výchozí IViewModelResolver s názvem ViewModelResolver (&lt;em&gt;ViewModelManager = () =&amp;gt;
new ViewModelResolver();)&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Rozhraní IViewModelResolver
&lt;/p&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/763365.js"&gt; &lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Metodě IsView předáte vybraný objekt a ona vám vrátí true, jestliže objekt považuje
za view, pro které by měl existovat view model. Metoda ResolveViewModel přijme objekt
představující view a dohledá k němu view model.
&lt;/p&gt;
&lt;p&gt;
Pro lepší představu vám mohu bez podrobnějšího komentáře ukázat třídu, která v aplikaci
používající Posterous API dohledá k view view model na základě jmenné konvence. Za
View se považuje každá instance z třídy, jejíž název končí znaky “View”, a k tomuto
View je vrácen view model, který se jmenuje stejně jako view, ale končí znaky “ViewModel”.
K view s názvem Login&lt;em&gt;View &lt;/em&gt;je tedy vrácen view model s názvem Login&lt;em&gt;ViewModel.&lt;/em&gt;
&lt;/p&gt;
&lt;script src="https://gist.github.com/763375.js"&gt; &lt;/script&gt;
&lt;p&gt;
Vraťme se k metodě restoreTransientState. Když metoda zjistí, že objekt představuje
view, pokusí se dohledat dříve uložený tranzientní stav. Stav je uložen pro každé
view v objektu IDictionary, konkrétně v třídě KnownTypesDictionary, pod klíčem, kterým
je úplné jméno ovládacího prvku – úplným jménem se rozumí jméno třídy ovládacího prvku
+ jména tříd všech jeho vizuálních předků (&lt;em&gt;ancestors&lt;/em&gt;). Ke jménu třídy každého
prvku je přidán pořadový indexu prvku mezi prvky na stejné úrovni vizuálního stromu.
Klíč generuje třída UIHelper v metodě GetTransientStateKey.
&lt;/p&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/763381.js"&gt; &lt;/script&gt;
Metoda restoreTransientState se poté s s využitím metody prepareViewModel pokusí získat
přes ViewModelManager view model (&lt;em&gt;ViewModelManager().ResolveViewModel(obj&lt;/em&gt;),
dále zjistí, jestli view model podporuje rozhraní ITransientStateManager, IInitialize
a a IActivated a pokračuje takto:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Jestliže máme uložen tranzientní stav (došlo k “tombstoningu”) a view model podporuje
rozhraní ITransientStateManager, zavoláme metodu LoadState z rozhraní ITransientStateManager
(&lt;em&gt;stateManager.LoadState(LastSavedTransientState[stateKey]); &lt;/em&gt;a view model
tak dostane šanci načíst dříve uložená tranzientní data.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Když nemáme uložen tranzientní stav a view model podporuje rozhraní IInitialize, zavoláme
metodu IInitialize.Init. View model tak dostane šanci nahrát data, ať už se souboru,
z webové služby nebo jiného datového zdroje, která mají být zobrazena v aktuálním
view.&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Poté, co view model obnoví nebo inicializuje svůj stav, je volána metoda activateAndSetDataContext,
která na view modelech podporujících rozhraní IActivated zavolá metodu Activate a
nastaví view model jako datový zdroj (“DataContext”) view.
&lt;/p&gt;
&lt;p&gt;
Nakonec pro všechny dceřiné prvky, které mohou představovat vnořená view (např. user
control), rekurzivně zavoláme opět metodu restoreTransientState. K získání dceřiných
prvků a jejich relativního indexu mezi prvky na stejné úrovni zanoření ve vizuálním
stromu je použita metoda UIHelper.GetChildren.
&lt;/p&gt;
&lt;script src="https://gist.github.com/763405.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metoda LoadState, restoreTransientState a další pomocné metody, o kterých jsme mluvili
v předchozích odstavcích:
&lt;/p&gt;
&lt;script src="https://gist.github.com/763410.js"&gt; &lt;/script&gt;
&lt;p&gt;
Za povšimnutí stojí ve scénáři metody restoreTransientState ještě několik dalších
věcí:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Když zjišťujeme, jestli objekt podporuje rozhraní IInitialize (metoda &lt;em&gt;getInitObjectWithSyncContext&lt;/em&gt;),
ihned do view modelu zpropagujeme synchronizační kontext (&lt;em&gt;initObject.SynchContext
= SynchronizationContext.Current&lt;/em&gt;;), aby například událost PropertyChanged mohla
být vyvolávána vždy v UI vláknu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Pomocná metoda &lt;em&gt;selectViewModel(frameworkElement, lastViewModel, currentViewModel);&lt;/em&gt; odpovědná
za výběr view modelu zajistí, že když IViewModelResolver nenalezne pro view žádný
view model, automaticky view přiřadí view model použitý u předchozího view. Kdy to
potřebujete? Třeba když stránku rozdělíte na několik nezávislých “user controls”,
tak se můžete rozhodnout, jestli bude mít každý user control (view) svůj view model,
nebo view model vytvoříte jen pro celou stránku a “user controls” view modely automaticky
“zdědí”. To byl jen jeden příklad - úroveň zanoření view je zcela ve vaší režii. Slovo
“zdědí” je v uvozovkách, protože nejde o klasické dědení DataContextu, ale k předání
posledně použitého view modelu dojde i tehdy, když dvě view nemají společné “nadview”.&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;em&gt;Poznámka: Nejprve jsem chtěl volání metod Init a LoadState na view modelech a
následné nastavení DataContextu u view dát do jiného vlákna. Problém je v tomto případě
s dědením view modelů. Když přiřadíte view model, na kterém jste zavolali asynchronně
metodu Init, dalšímu vnořenému View, tak se může stát, že metoda Init ještě nedoběhla,
view model u prvního view nastaven není, ale u vnořeného (druhého) view již nastaven
je, což může vést k podivným a kvůli použití více vláken obtížně reprodukovatelným
chybám. Za asynchronní zpracování časově náročných scénářů zodpovídají samotné view
modely, které by měly přepisovat virtuální metodu DoInternalAsyncInit z ViewModelBase.
Metodu DoInternalAsyncInit jsem &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;popisoval
v předchozím článku&lt;/a&gt;.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Viděli jsme, kdy hostitel volá metody Init, Activate a kdy voláním metody LoadState
obnoví tranzientní stav ve view modelech. Ještě nám zbývá projít, kdy ukládáme tranzientní
stav a kdy notifikujeme view modely voláním jejich metody Deactivate o tom, že k nim
přidružené view (stránka) není již aktivní.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Nebudeme při ukládání tranzientního stavu nijak pátrat, jestli došlo k “tombstoningu”,
ale stav view modelů do &lt;em&gt;PhoneApplicationPage.State&lt;/em&gt; uložíme vždy, když dojde
k opuštění stránky. Hlavním důsledkem tohoto rozhodnutí je, že s obsluhou metod&amp;nbsp;
Application_Launching, Application_Activated, Application_Deactivated a Application_Closing,
kterou jsem popisoval minule, se nemusíte kvůli “tombstoningu” trápit a zmíněné metody
můžete většinou zcela ignorovat.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
O opuštění stránky jsm informováni v metodě OnNavigatedFrom, kterou přepíšeme. Metoda
OnNavigatedFrom voláním metody SaveState uloží stav všech view modelů a poté metoda
handleAllDeactivated na všech modelech&amp;nbsp; podporujících rozhraní IDeactivated zavolá
metodu Deactivate.
&lt;/p&gt;
&lt;script src="https://gist.github.com/763441.js"&gt; &lt;/script&gt;
&lt;p&gt;
Popisovat kompletně logiku v metodě SaveState nemá smysl, protože tato metoda je reverzní
k metodě LoadState. Pro všechny view rekurzivně vyhledá jejich view modely a dovolí
jim uložit pod unikátním klíčem view, který je vygenerován třídou UIHelper, tranzientní
stav. Ten samý tranzientní stav view modelů, jehož obnovení v metodě LoadState jsem
popisoval výše.&amp;nbsp; &lt;script src="https://gist.github.com/763445.js"&gt; &lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Za komentář stojí, že podmínka if&lt;em&gt; (stateManager != null &amp;amp;&amp;amp; stateManager
!= lastDataContext) &lt;/em&gt;ošetřuje, abychom neukládali trazientní stav view modelu,
který slouží jako DataContext u více View, opakovaně, ale vždy pouze jednou.
&lt;/p&gt;
&lt;p&gt;
Tranzientní stav všech view modelů je ukládán do speciálního objektu Dictionary s
názvem KnownTypesDictionary.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;var statebag = new KnownTypesDictionary();&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Připomínám, že při tombstoningu je možné uložit jen serializovatelné objekty. Představme
si nyní, že KnownTypesDictionary je potomek třídy&amp;nbsp; Dictionary&amp;lt;string, object&amp;gt;.
Do takového objektu Dictionary můžeme vložit kteroukoli instanci z třídy, která je
přímo či nepřimo potomkem třídy Object, ale při pokusu o serializaci dostaneme chybu,
protože naše potomky DataContractSerializer nezná a očekává, že v kolekci budou jen
instance třídy Object, a ne instance odvozených tříd. Pomocí atributu &lt;a href="http://msdn.microsoft.com/en-gb/library/system.runtime.serialization.knowntypeattribute.aspx"&gt;KnownType&lt;/a&gt;,
který je aplikován na KnownTypesDictionary, můžeme DataContractSerializer informovat,
které všechny třídy má v objektu Dictionary očekávat. Jednou z&amp;nbsp; možností, jak
to udělat, je předat atributu KnownType název statické metody, která seznam “známých”
tříd vrací. 
&lt;/p&gt;
&lt;p&gt;
Dnes si ukážeme jednoduchou verzi třídy&amp;nbsp; &lt;em&gt;KnownTypesDictionary&lt;/em&gt;, která
v metodě GetKnownTypes vrátí fixní seznam "známých” tříd. Příště si ukážeme, jak budou
“známé” třídy dohledány a registrovány&amp;nbsp; automaticky bez nutnosti vytvářet seznam
známých tříd vždy znovu a “natvrdo” v každé aplikaci. V dalších dílech také zjistíme,
jak právě vytvořená infrastruktura nám dovolí vytvářet WP7 aplikace příslovečným lusknutím
prstu, tedy spíš nečetným lusknutím prstů o klávesnici. &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/8b4a80e9bf58_926F/wlEmoticon-smile_2.png"&gt; &lt;script src="https://gist.github.com/763469.js"&gt; &lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Předcházející články: 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;Tipy
pro Windows Phone 7 aplikace I&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=38539832-2f1d-42cf-8549-b59697b093c4" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,38539832-2f1d-42cf-8549-b59697b093c4.aspx</comments>
      <category>Compact .Net Framework</category>
      <category>Návrhové vzory</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=060fbd09-0368-4733-92ad-aaecf48409a4</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,060fbd09-0368-4733-92ad-aaecf48409a4.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,060fbd09-0368-4733-92ad-aaecf48409a4.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=060fbd09-0368-4733-92ad-aaecf48409a4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
 
</p>
        <p>
Již v <a href="http://Tipy pro Windows Phone 7 aplikace I">prvním dílu seriálu o vývoji
WP7 aplikací</a> jsem zmiňoval nejen to, že mobilní verze Silverlightu ve WP7 je založena
na Silverlightu 3, ale také, že mobilní Silverlight má své unikátní rysy, které v
žádné desktopové verzi Silverlightu nenalezneme. Jednou ze změn je životní cyklus
aplikace, včetně tzv. tombstoningu. Termín ”tombstoning”, kterého se i  v tomto
článku budu držet, abych nemusel zavádět nějaké směšně znějící české ekvivalenty,
má asi naznačovat, že WP7 podporují nejen tradiční spuštění a ukončení aplikace, ale
i jakýsi hybridní stav, v němž instance naší aplikace může být dočasně ukončena (“umrtvena”)
například tím, že uživatel spustí jinou aplikaci, a poté může být z hlediska uživatele
WP7 telefonu naše původní aplikace navrácena k životu,  a to dokonce ve stavu,
v jakém ji předtím uživatel zanechal. O smysluplnosti “tombstoningu” mám své pochybnosti
a raději bych ve WP7 viděl tradiční multitasking, ale vývojářův boj s chováním “zombie”
aplikací ve stavu “tombstoningu” má také něco do sebe. V tomto článku bych rád posunul
boj se “zombie-tombstonovanými” aplikacemi do dalšího levelu a nabídnul pár “cheatů”
.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-II_A042/wlEmoticon-smile_2.png" /></p>
        <p>
Přechody mezi stavy WP7 aplikace nám nejlépe objasní  metody pro obsluhu životního
cyklu aplikace, které jsou po založení projektu automaticky vygenerovány v souboru
App.xaml.cs.
</p>
        <script src="https://gist.github.com/744872.js">
        </script>
        <p>
Metoda  <em>Application_Launching </em>je  provedena jednou po spuštění
aplikace. Jde o metodu, ve které můžete načíst dříve uložená data z “isolated storage”. 
Tato metoda NENÍ volána při  obnovení “tombstonované” aplikace.
</p>
        <p>
Metoda <em>Application_Closing </em>je provedena jednou při ukončení aplikace. Jde
o metodu, ve které typicky uložíte data do “isolated storage”. Jde o stejná data,
která  načtete při dalším spuštění aplikace v již popsané metodě <em>Application_Launching </em>a
můžeme tedy říci, že jde o data s delší záruční lhůtou<em>, </em>která mají význam
pro různé instance aplikace. Když stáhnete z webové služby nějaké číselníky (typy
zákazníků, kategorie objednávek) a nechcete je po startu aplikace stahovat vždy znovu,
uložíte si je a při příštím spuštění aplikace rychleji naběhne, protože nemusí stahovat
všechna data z webových služeb ihned po startu.
</p>
        <p>
Další metody se týkají již tombstoningu. Metoda <em>Application_Deactivated</em> je
volána vždy, když je vaše aplikace “tombstonována” a v této metodě byste měli uložit
všechna data, která potřebujete k tomu, abyste mohli po návratu z “tombstonovaného”
stavu aplikaci zobrazit uživateli tak, jako kdyby běžela celou dobu a k žádnému “tombstoningu”
nedošlo. Pro vývojáře ale “tombstoning” ve skutečnosti znamená, že aktuálně běžící
instance aplikace je zlikvidována! Můžeme tedy říci, že v této metodě hlavně ukládáme
data s kratší záruční lhůtou, která mají význam jen pro další instanci aplikace po
návratu z “tombstonovaného” stavu. Data, která chcete mít k dispozici i po obnovení
z “tombstoningu” můžete ukládat pod vámi zvolenými identifikátory v objektu typu IDictionary
ve vlastnosti PhoneApplicationService.Current.State. <strong>Data, která zde uložíte,
musí být serializovatelná, protože se nedrží jen v paměti telefonu, ale jsou ukládána
i do souboru.</strong></p>
        <p>
Je ale nutné si uvědomit, že když je aplikace “tombstonována”, nemáte garantováno,
že se uživatel do vaší aplikace vrátí a že budete obnoveni z “tombstonovaného” stavu.
I v této metodě je proto vhodné ukládat data, která ukládáte v metodě <em>Application_Closing </em>popsané
výše. 
</p>
        <p>
Uživatel může také spustit vaší aplikaci znovu, tedy spustit novou instanci aplikace,
aniž by se vrátil k dříve “"tombstonované” aplikaci a vy svůj stav - data, o nichž
jsem říkal, že mají kratší záruční lhůtu - dříve uložený v metodě <em>Application_Deactivated </em>nikdy
nepoužijete. Když se uživatel vrátí do vaší aplikace, což většinou nastane po stisknutí
tlačítko “Back”, kdy se v zásobníku dříve spuštěných aplikací, který je spravován
přímé operačním systémem, stane aktivním vaše aplikace, musíte obnovit dříve uložený
stav v metodě <em>Application_Activated</em>. Napsal jsem, že jde o zásobník aplikací,
ale je potřeba si uvědomit, že jde spíš o metaforu, protože aplikace a jejich stránky
nejsou nikdy fyzicky uloženy, ale při “tombstoningu” většinou bez milosti zlikvidovány,
a metoda <em>Application_Activated </em>je volána v nové instanci naší aplikace. WP7
si jen v zásobníku pamatují, jaké aplikace a v jakém pořadí byly  spuštěny a
která stránka v konkrétní aplikaci byla aktivní. 
</p>
        <p>
Dále je potřeba si osvojit tato pravidla:
</p>
        <ul>
          <li>
Metoda <em>Application_Activated </em><strong>NENÍ</strong> volána po spuštění nové
(“netombstonované”) instance aplikace. Po spuštění nové (“netombstonované”) instance
aplikace je volána pouze metoda <em>Application_Launching.<br /></em></li>
          <li>
Metoda <em>Application_Deactivated</em><strong>NENÍ</strong> volána při  úplném
ukončení aplikace. Při  úplném ukončení aplikace je volána pouze metoda <em><em>Application_Closing</em>.</em></li>
        </ul>
        <p>
Zjednodušeně bychom mohli odpovědnosti metod v souboru App.xaml.cs popsat tímto fragmentem
kódu:
</p>
        <script src="https://gist.github.com/744916.js">
        </script>
        <p>
Měli bychom ale vědět, že k tombstoningu může dojít kdykoli a podle mých testů na
emulátoru i reálném zařízení může být aplikace “tombstonována”, i když se zrovna obnovuje
z předchozího “tombstonovaného” stavu a je v metodě “<em>Application_Activated“.  </em>Autoři
WP7 se s “tombstoningem” moc nepatlají a bez skrupulí po určité době zlikvidují vlákna
aplikace, což poznáte podle výjimky <em>ThreadAbortException.</em></p>
        <p>
Také se mi nelíbí, že bych měl v tomto jediném souboru ukládat a obnovovat data pro
všechny stránky (“formuláře”) aplikace. Rozhodl jsem se, že na obsluhu těchto metod
rezignuju a místo životní cyklu aplikace se budu zajímat jen o životní cyklus view
modelu (presentation modelu, chcete-li) u každé stránky ve WP7 aplikaci.
</p>
        <p>
Dnes si ukážeme bázovou třídu pro view modely a další podpůrné třídy se službami,
která nás svou spoluprací zbaví nutnosti při psaní každé stránky myslet na to, že
autoři WP7 aplikací se vyžívají v recidivě nekrofilního chování u WP7 aplikací. Drahý
bratr Sigmund Freud by se po prohlídce stavového automatu “tombstonované“ aplikace
od architektů WP7 na své pohovce jistě tetelil radostí nad předaným šokujícím materiálem. <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-II_A042/wlEmoticon-smile_2.png" /></p>
        <p>
Nejdříve si ale navrhneme minimální množinu vlastností, kterou by měl každý view model
splňovat, abychom se již nemuseli životním cyklem WP7 aplikace příliš zabývat při
návrhu každé stránky.
</p>
        <ol>
          <li>
Musíme být schopni nahrát data při vytvoření nového view modulu. Také bychom měli
zajistit, že když dojde k “tombstoningu” aplikace ještě před získáním všech dat, nezůstane
view model v nějakém nekonzistentním stavu s třetinou nahraných dat, ale po obnovení
z “tombstoningu” dostane šanci nahrát data znovu. 
<br /><br /><script src="https://gist.github.com/744974.js"></script></li>
          <li>
Budeme schopni při “tombstoningu” automaticky perzistovat dočasný stav každého view
modelu. Od této chvíle začneme říkat dočasnému stavu stav tranzientní.<em> V tomto
článku se zabývám jen tranzientním stavem aplikace, o perzistování “trvanlivějších”
dat do “isolated storage” se pobavíme v některém z dalších článků.</em><br /></li>
          <li>
Po obnovení aplikace z “tombstonovaného” stavu každý view model automaticky nahraje
svůj tranzientní stav.<br />
Pro uložení a nahrání tranzientního stavu nadefinujeme rozhrani ITransientStateManager.<br /><br /><script src="https://gist.github.com/744980.js"></script></li>
          <li>
Měli bychom dát šanci view modelům zareagovat na to, že stránka, ke které jsou přidruženy,
se stala aktivní stránkou, i na to, že k nim přidružená stránka aktivní už není, ať
už proto, že došlo k “tombstoningu” nebo uživatel přešel na jinou stránku v aplikaci.<br />
Pro tyto účely máme rozhraní IActivated a IDeactivated.<br /><br /><script src="https://gist.github.com/744991.js"></script></li>
          <li>
Budeme mít sice bázovou třídu pro view modely, ale její použití si nebudeme vynucovat.
View model může být v aplikaci kterákoli třída. I když tato třída nebude potomkem
bázové třídy pro view modely, bude moci volitelně využít většinu služeb, které jsou
popsány v přechozích bodech.<br /><br /></li>
          <li>
Jedná se o view modely, měli bychom tedy na úrovní bázové třídy podporovat rozhraní
INotifyPropertyChanged, které nám dovoluje notifikovat o změně hodnoty ve vlastnostech
view modelu. Rozhraní INotifyPropertyChanged je ve WPF i v Silverlight aplikacích
všudypřítomné, proto si navrhneme další bázovou třídu PropertyChangedBase, která nám
kromě implementace rozhraní INotifyPropertyChanged přinese další užitečné služby.<br /><script src="https://gist.github.com/745001.js"></script></li>
        </ol>
        <p>
 
</p>
        <p>
Jaké další užitečné služby má třída PropertyChangedBase?
</p>
        <p>
Nemusíme vyvolávat událost PropertyChanged zadáním jen zadáním názvu vlastnosti (<em>RaisePropertyChanged(“UserName”)</em>),
což může vést k chybě za běhu aplikace, když uděláme překlep v názvu vlastnosti (<em>(RaisePropertyChanged(“UseName”)</em>),
ale můžeme předat název vlastnosti ve formě lambda výrazu, jehož syntaxe je zkontrolována
již kompilátorem. K tomu nám slouží metoda <em>RaisePropertyChangedEvent<treturn>
(Expression<func><treturn>
&gt; propertyDefinition)
</treturn></func></treturn></em>. Potomci třídy PropertyChangedBase mohou o změně hodnoty vlastnosti
informovat takto:
</p>
        <script src="https://gist.github.com/745018.js">
        </script>
        <p>
U potomků třídy PropertyChangedBase, kterými budou i naše view modely, si můžeme také
zavoláním metody <em>RaiseAllPropertiesChanged</em> vynutit vyvolání události o změně
hodnoty pro každou vlastnost. Další metodě s názvem <em>RaisePropertiesChanged(params
string[] properties) </em>můžeme předat názvy vlastností, pro které má být vyvolána
metoda PropertyChanged.
</p>
        <p>
A teď si  již můžeme vytvořit slibovanou třídu ViewModelBase, která je potomkem
třídy PropertyChangedBase a podporuje všechna rozhraní zmíněná dříve.
</p>
        <script src="https://gist.github.com/745046.js">
        </script>
        <p>
 
</p>
        <p>
V konstruktoru třída ViewModelBase přijímá titulek zobrazované stránky, který je uložen
do vlastnosti PageTitle.
</p>
        <script src="https://gist.github.com/745079.js">
        </script>
        <p>
Metoda Init z rozhraní Initialize by měla být volána vždy, když je view model vytvořen,
nebo když je po obnovení aplikace z “tombstonovaného” stavu zřejmé, že view model
nenahrál všechna data, což se zjistí voláním virtuální metody <em>IsAllInitDataLoaded</em>,
která v této abstraktní třídě vždy  vrací true a čeká na to, až odvozené konkrétní
view modely dosadí svou logiku, kdy je považován view model za nahraný. Metoda Init
by měla být taky volána, když odvozený view model obnovená tranzientní data považuje
za špatná / zastaralá a nemůže je používat, což nám dá najevo nastavením vlastnosti <em>IsInvalidModel</em> na
true. K rychlému zjištění, jestli  je možné view model dále používat slouží derivovaná
vlastnost <em>CanUseModel</em>, která spojuje logiku obsaženou ve vlastnosti <em>IsInvalidModel</em> a
metodě <em>IsAllInitDataLoaded.</em></p>
        <script src="https://gist.github.com/745094.js">
        </script>
        <p>
 
</p>
        <p>
Metoda <em>Initialize.Init</em></p>
        <script src="https://gist.github.com/745104.js">
        </script>
        <p>
V metodě <em>Init</em> nejdříve nastavíme vlastnost <em>IsInvalidModel</em> na true,
protože naše metoda <em>Init</em> probíhá a kdyby došlo k “tombstoningu”, nemáme všechna
data a je potřeba volat metodu <em>Init</em> znovu. Poté jen načteme titulek aplikace
do vlastnosti <em>AppTitle</em>,  inicializujeme vlastnost <em>SuppressValidating</em>,
která slouží k dočasnému potlačení ověřování platnosti data zadaných uživatelem ve
view modelu, na hodnotu false. <em>O vlastnosti SuppressValidating budeme více mluvit
v dalším článku včetně vysvětlení významu metody ValidateData a vlastnosti HasValidData. 
<br /></em></p>
        <p>
Dále <em>ViewModelBase</em> nastavením vlastnosti <em>IsInvalidModel</em> na false
sděluje, že jeho inicializace proběhla, všechna data v modelu považuje za platná a
dá šanci odvozeným třídám, aby inicializovaly svá data voláním chráněné virtuální
metody <em>DoInternalInit</em>, která má ve <em>ViewModelBase</em> prázdnou implementaci
a do které odvozené třídy dají svou specifickou logiku pro načtení dat. Vlastnost <em>IsInvalidModel</em> mohou
samozřejmě odvozené třídy nastavit v metodě <em>DoInternalInit</em> opět na true,
ale my ve vlastnosti <em>IsInvalidModel</em> hodnotu true nenecháváme, protože si
přepsání metody <em>DoInternalInit</em> v odvozených třídách nevynucujeme a v bázové
třídě ViewModelBase nemůžeme vědět, kdy odvozené třídy považují svá data za neplatná.
</p>
        <p>
V metodě <strong>Init </strong>nakonec také voláním metody další chráněné virtuální
metody s názvem <em>DoInternalAsyncInit</em> v <strong>samostatném vlákně </strong>šanci
odvozeným třídám <strong>asynchronně </strong>inicializovat svá data. Metodu <em>DoInternalAsyncInit</em> by
měly odvozené třídy používat k časově náročné inicializaci, kterou není vhodné vhodné
dávat do synchronně  volané metody DoInternalInit a blokovat tak hlavní thread
aplikace.
</p>
        <p>
Mohlo by vás také zaujmout, že v sekci catch má speciální zacházení výjimka <em>ThreadAbortException
– </em>tato výjimka není propagována výše, protože ji vyvolá samotné běhové prostředí
Silverlightu při násilném “tombstoningu”, jak jsem poznamenal na začátku tohoto článku.
</p>
        <p>
 
</p>
        <p>
Rozhraní <em>IActivated</em> s metodou <strong>Activate </strong>a<strong></strong>rozhraní<strong></strong><em>IDeactivated </em>s
metodou <strong>Deactivate</strong> ve <em>ViewModelBase</em> mají jen prázdnou implementaci
a čekají na to, jakou logiku do nich vloží odvozené třídy. Mimochodem  – na tomto
místě bychom měli poprvé vytušit, že budeme potřebovat “hostitele” našich view modelů,
který bude vědět, kdy volat metody <em>Activate</em>, <em>Deactivate</em>, <em>Init</em> a
další.<br /></p>
        <p>
Třída ViewModelBase explicitně implementuje rozhraní <em>ITransientStateManager</em>,
které jsme si zavedli pro podporu automatického ukládání a nahrávání tranzientního
stavu. Metody <em>LoadState</em> a <em>SaveState</em> ale po svém vyvolání jen předají
řízení chráněným virtuálním metodám <em>DoInternalLoadTransientState</em> a <em>DoInternalSaveTransientState, </em>aby
dali šanci i odvozeným třídám změnit způsob uložení a nahrání tranzientního stavu,
i když odvozené třídy jsou většinou spokojeni s tím, že to za ně zvládne předek ViewModelBase.
</p>
        <p>
 
</p>
        <script src="https://gist.github.com/745208.js">
        </script>
        <p>
Třída ViewModelBase ve svém statickém konstruktoru dosazuje výchozí objekt podporující
rozhraní <em>ITransientStateHelper</em>, které je klíčové pro uložení a obnovení tranzientního
stavu view modelů a na které delegují i metody <em>DoInternalLoadTransientState</em> 
a <em>DoInternalSaveTransientState</em> v předchozím výpisu.
</p>
        <p>
Všimněte si, že metoda <em>DoInternalLoadTransientState </em>po obnovení tranzientního
stavu zkontroluje, jestli se dá view model používat, a pokud ne, zavolá i v této fázi
metodu Init.
</p>
        <p>
          <em>if (!CanUseModel)<br />
{</em>
        </p>
        <p>
          <em>  Init();<br />
}</em>
        </p>
        <p>
A nyní se podíváme na mocné rozhraní <em>ITransientStateHelper</em></p>
        <strong>
        </strong>
        <script src="https://gist.github.com/745212.js">
        </script>
        <p>
Je asi zřejmé, že metoda <em>GetTransientState</em> vrátí v objektu Dictionary tranzientní
stav objektu, který jí byl předán v argumentu obj. Metoda <em>RestoreTransientState</em> naopak
obnoví tranzientní stav objektu v argumentu obj hodnotami v argumentu savedState.
</p>
        <p>
Metoda <em>IsTransientStateEnabledForObject</em> zjistí, jestli je možné z předaného
objektu získat tranzientní stav. Jak uvidíme, odvozené view modely mohou odmítnout
uložení tranzientního stavu a kdekoli v aplikaci  můžeme jejich rozhodnutí jednoduše
zjistit předáním instance view modelu této metodě.
</p>
        <p>
Zde je jedna z možných realizací rozhraní IStateTransientStateHelper, kterou používá
i naše třída ViewModelBase.
</p>
        <script src="https://gist.github.com/745247.js">
        </script>
        <p>
 
</p>
        <p>
Odpovědnosti metod <em>GetTransientState</em> a <em>RestoreTransientState</em> jsem
již popsal, nyní jen zmíním pár specialitek v kódu třídy TransientStateHelper.
</p>
        <p>
Metoda GetTransientState zjistí, jestli předaný objekt  má tranzientní stav tak,
že zavolá metodu <strong>IsTransientStateEnabledForObject(obj)<em>.</em></strong></p>
        <p>
Metoda IsTransientStateEnabledForObject kontroluje, jestli třída, ze které objekt
pochází, nezakázala vydání tranzientního stavu tím, že je na ní aplikován atribut
[NonTransientState].
</p>
        <p>
Atribut NonTransientState
</p>
        <script src="https://gist.github.com/745279.js">
        </script>
        <p>
Atribut NonTransientState může být aplikován nejen na celou třídu, ale i na jednotlivé
vlastnosti objektu, které nemají být součástí tranzientního stavu.  <strong>Metoda
GetTransientState neukládá celé view modely, ale s využitím reflexe jen hodnoty jejich
vlastností. Atribut NonTransientState dovoluje vyřadit vlastnosti, které v tranzientním
stavu view modelu nemají co dělat.</strong> To ale není vše – přímo metoda GetTransientState
dle jmenné konvence vyřadí všechny vlastnosti, jejichž suffix je v poli IGNORE_METHOD_SUFFIX_LIST 
</p>
        <p>
          <em>public static readonly IEnumerable<string>
IGNORE_METHOD_SUFFIX_LIST = new[] { "Command", "Action", "Helper", "Service", "SynchContext"};
</string></em>
        </p>
        <p>
Do tranzientního stavu se tak nedostanou ve view modelech se často nacházející, ale
s tranzientním stavem view modelu nic nemající a navíc většinou neserializovatelné
objekty jako jsou objekty ICommand (vlastnost Select<strong>Command</strong>, Save<strong>Command</strong>),
delegáti  TextboxTextChanged<strong>Action</strong>, služby (ILogger<strong>Service</strong>)
a další.
</p>
        <p>
Metoda <em>RestoreTransientState</em> obnoví tranzientní stav objektu. Za zmínku stojí,
že když je předaný objekt potomkem PropertyNotificationBase, tak nastavením vlastnosti
notificationBase.SuppressPropertyChangedNotification na true potlačíme dočasně vyvolání
události OnPropertyChanged, protože je vhodné, abychom událost nevyvolávali, když
view model neobsahuje všechna data a nevíme, kdo všechno na událost reaguje a jaká
další, nyní ve view modelu se nenacházející data, by chtěl načíst. Jak jsem ale psal
v požadavcích na začátku článku, view model nemusí podporovat žádná rozhraní, nemusí
být potomkem ViewModelBase ani PropertyNotificationBase, a proto si ani dědění z PropertyNotificationBase
v této metodě nevynucujeme. Poté, co metoda <em>RestoreTransientState </em>obnoví
hodnoty všech vlastností, má TransientStateHelper povinnost notifikovat okolí o změně
hodnot všech vlastností view modelu. Jestliže je objekt s obnoveným tranzientním stavem
potomkem PropertyNotificationBase, zavoláme metodu RaisePropertiesChanged(propertyNames.ToArray()),
jinak se metoda <em>RestoreTransientState</em> pokusí dohledat opět za pomoci reflexe
na objektu metodu nazvanou RaisePropertyChangedEvent, která přijímá název vlastnosti
a kterou použije pro hromadnou distribuci událostí OnPropertyChanged.
</p>
        <p>
Ovládací prvky obsažené (nejen) v control toolkitu jsou  přecitlivělé na pořadí
vyvolávání události, a proto jsou vlastnosti seřazeny nyní tak, aby vlastnosti začínající
slovem <em>Selected</em><strong></strong>vyvolávaly událost OnPropertyChanged jako
poslední. Máte-li ve view modelu kolekci nazvanou Orders (všechny objednávky) a SelectedOrder
(vybraná objednávka z této kolekce), je zaručeno, že <strong>událost OnPropertyChanged
pro vlastnost SelectedOrder bude vyvolána až po události OnPropertyChanged pro vlastnost
Orders.</strong></p>
        <p>
          <em>Prefixy vlastností, které mají vyvolávat události jako poslední, jsou v proměnné
LAST_SET_VALUE_METHOD_PREFIX. Tyto vlastnosti jsou označeny příznakem LastInit z enumerace
PropertyType.</em>
        </p>
        <p>
          <em>
          </em>
        </p>
        <p>
          <em>public static readonly IEnumerable<string>
LAST_SET_VALUE_METHOD_PREFIX = new[] { "Selected" };
</string></em>
        </p>
        <p>
To by pro dnešek k třídě ViewModelBase a jejím pomocníkům stačilo:
</p>
        <p>
Příště se podíváme hlavně na “hostitele” view modelů, který by měl být schopen:
</p>
        <ul>
          <li>
Volat na view modelech ve “správnou dobu” metody Init, LoadState, SaveState, Activate,
Deactivate. 
<br /></li>
          <li>
Připojit view modely k view (stránce).<br /></li>
          <li>
Náš hostitel bude podporovat i více view modelů na jedné stránce, včetně “dědění”
a sdílení použitých view modelů mezi různými view na stránce.</li>
        </ul>
        <p>
A také si příště vysvětlíme, proč při získání tranzientního stavu ve ViewModelbase
místo objektu Dictionary používáme vlastní třídu KnownTypesDictionary. Jak možná tušíte,
i název “KnownTypes” odkazuje k tomu, že mají-li být hodnoty uložené v tranzientním
stavu serializovatelné, tak <em>DataContractSerializer,</em> používaný infrastrukturou
WP7 k serializaci tranzientního stavu, musíme přesvědčit, že v objektu Dictionary
jsou jen objekty z jemu “známých” tříd.
</p>
        <p>
Předcházející články:
</p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">Tipy
pro Windows Phone 7 aplikace I</a>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=060fbd09-0368-4733-92ad-aaecf48409a4" />
      </body>
      <title>Tipy pro Windows Phone 7 aplikace II &amp;ndash; podpora životn&amp;iacute;ho cyklu aplikace (včetně tombstoningu) ve &amp;quot;view modelech&amp;rdquo;</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,060fbd09-0368-4733-92ad-aaecf48409a4.aspx</guid>
      <link>http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx</link>
      <pubDate>Fri, 17 Dec 2010 18:25:14 GMT</pubDate>
      <description>&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Již v &lt;a href="http://Tipy pro Windows Phone 7 aplikace I"&gt;prvním dílu seriálu o vývoji
WP7 aplikací&lt;/a&gt; jsem zmiňoval nejen to, že mobilní verze Silverlightu ve WP7 je založena
na Silverlightu 3, ale také, že mobilní Silverlight má své unikátní rysy, které v
žádné desktopové verzi Silverlightu nenalezneme. Jednou ze změn je životní cyklus
aplikace, včetně tzv. tombstoningu. Termín ”tombstoning”, kterého se i&amp;nbsp; v tomto
článku budu držet, abych nemusel zavádět nějaké směšně znějící české ekvivalenty,
má asi naznačovat, že WP7 podporují nejen tradiční spuštění a ukončení aplikace, ale
i jakýsi hybridní stav, v němž instance naší aplikace může být dočasně ukončena (“umrtvena”)
například tím, že uživatel spustí jinou aplikaci, a poté může být z hlediska uživatele
WP7 telefonu naše původní aplikace navrácena k životu,&amp;nbsp; a to dokonce ve stavu,
v jakém ji předtím uživatel zanechal. O smysluplnosti “tombstoningu” mám své pochybnosti
a raději bych ve WP7 viděl tradiční multitasking, ale vývojářův boj s chováním “zombie”
aplikací ve stavu “tombstoningu” má také něco do sebe. V tomto článku bych rád posunul
boj se “zombie-tombstonovanými” aplikacemi do dalšího levelu a nabídnul pár “cheatů”
.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-II_A042/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
Přechody mezi stavy WP7 aplikace nám nejlépe objasní&amp;nbsp; metody pro obsluhu životního
cyklu aplikace, které jsou po založení projektu automaticky vygenerovány v souboru
App.xaml.cs.
&lt;/p&gt;
&lt;script src="https://gist.github.com/744872.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metoda&amp;nbsp; &lt;em&gt;Application_Launching &lt;/em&gt;je&amp;nbsp; provedena jednou po spuštění
aplikace. Jde o metodu, ve které můžete načíst dříve uložená data z “isolated storage”.&amp;nbsp;
Tato metoda NENÍ volána při&amp;nbsp; obnovení “tombstonované” aplikace.
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;Application_Closing &lt;/em&gt;je provedena jednou při ukončení aplikace. Jde
o metodu, ve které typicky uložíte data do “isolated storage”. Jde o stejná data,
která&amp;nbsp; načtete při dalším spuštění aplikace v již popsané metodě &lt;em&gt;Application_Launching &lt;/em&gt;a
můžeme tedy říci, že jde o data s delší záruční lhůtou&lt;em&gt;, &lt;/em&gt;která mají význam
pro různé instance aplikace. Když stáhnete z webové služby nějaké číselníky (typy
zákazníků, kategorie objednávek) a nechcete je po startu aplikace stahovat vždy znovu,
uložíte si je a při příštím spuštění aplikace rychleji naběhne, protože nemusí stahovat
všechna data z webových služeb ihned po startu.
&lt;/p&gt;
&lt;p&gt;
Další metody se týkají již tombstoningu. Metoda &lt;em&gt;Application_Deactivated&lt;/em&gt; je
volána vždy, když je vaše aplikace “tombstonována” a v této metodě byste měli uložit
všechna data, která potřebujete k tomu, abyste mohli po návratu z “tombstonovaného”
stavu aplikaci zobrazit uživateli tak, jako kdyby běžela celou dobu a k žádnému “tombstoningu”
nedošlo. Pro vývojáře ale “tombstoning” ve skutečnosti znamená, že aktuálně běžící
instance aplikace je zlikvidována! Můžeme tedy říci, že v této metodě hlavně ukládáme
data s kratší záruční lhůtou, která mají význam jen pro další instanci aplikace po
návratu z “tombstonovaného” stavu. Data, která chcete mít k dispozici i po obnovení
z “tombstoningu” můžete ukládat pod vámi zvolenými identifikátory v objektu typu IDictionary
ve vlastnosti PhoneApplicationService.Current.State. &lt;strong&gt;Data, která zde uložíte,
musí být serializovatelná, protože se nedrží jen v paměti telefonu, ale jsou ukládána
i do souboru.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Je ale nutné si uvědomit, že když je aplikace “tombstonována”, nemáte garantováno,
že se uživatel do vaší aplikace vrátí a že budete obnoveni z “tombstonovaného” stavu.
I v této metodě je proto vhodné ukládat data, která ukládáte v metodě &lt;em&gt;Application_Closing &lt;/em&gt;popsané
výše. 
&lt;/p&gt;
&lt;p&gt;
Uživatel může také spustit vaší aplikaci znovu, tedy spustit novou instanci aplikace,
aniž by se vrátil k dříve “"tombstonované” aplikaci a vy svůj stav - data, o nichž
jsem říkal, že mají kratší záruční lhůtu - dříve uložený v metodě &lt;em&gt;Application_Deactivated &lt;/em&gt;nikdy
nepoužijete. Když se uživatel vrátí do vaší aplikace, což většinou nastane po stisknutí
tlačítko “Back”, kdy se v zásobníku dříve spuštěných aplikací, který je spravován
přímé operačním systémem, stane aktivním vaše aplikace, musíte obnovit dříve uložený
stav v metodě &lt;em&gt;Application_Activated&lt;/em&gt;. Napsal jsem, že jde o zásobník aplikací,
ale je potřeba si uvědomit, že jde spíš o metaforu, protože aplikace a jejich stránky
nejsou nikdy fyzicky uloženy, ale při “tombstoningu” většinou bez milosti zlikvidovány,
a metoda &lt;em&gt;Application_Activated &lt;/em&gt;je volána v nové instanci naší aplikace. WP7
si jen v zásobníku pamatují, jaké aplikace a v jakém pořadí byly&amp;nbsp; spuštěny a
která stránka v konkrétní aplikaci byla aktivní. 
&lt;/p&gt;
&lt;p&gt;
Dále je potřeba si osvojit tato pravidla:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Metoda &lt;em&gt;Application_Activated &lt;/em&gt;&lt;strong&gt;NENÍ&lt;/strong&gt; volána po spuštění nové
(“netombstonované”) instance aplikace. Po spuštění nové (“netombstonované”) instance
aplikace je volána pouze metoda &lt;em&gt;Application_Launching.&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
Metoda &lt;em&gt;Application_Deactivated&lt;/em&gt; &lt;strong&gt;NENÍ&lt;/strong&gt; volána při&amp;nbsp; úplném
ukončení aplikace. Při&amp;nbsp; úplném ukončení aplikace je volána pouze metoda &lt;em&gt;&lt;em&gt;Application_Closing&lt;/em&gt;.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Zjednodušeně bychom mohli odpovědnosti metod v souboru App.xaml.cs popsat tímto fragmentem
kódu:
&lt;/p&gt;
&lt;script src="https://gist.github.com/744916.js"&gt; &lt;/script&gt;
&lt;p&gt;
Měli bychom ale vědět, že k tombstoningu může dojít kdykoli a podle mých testů na
emulátoru i reálném zařízení může být aplikace “tombstonována”, i když se zrovna obnovuje
z předchozího “tombstonovaného” stavu a je v metodě “&lt;em&gt;Application_Activated“.&amp;nbsp; &lt;/em&gt;Autoři
WP7 se s “tombstoningem” moc nepatlají a bez skrupulí po určité době zlikvidují vlákna
aplikace, což poznáte podle výjimky &lt;em&gt;ThreadAbortException.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Také se mi nelíbí, že bych měl v tomto jediném souboru ukládat a obnovovat data pro
všechny stránky (“formuláře”) aplikace. Rozhodl jsem se, že na obsluhu těchto metod
rezignuju a místo životní cyklu aplikace se budu zajímat jen o životní cyklus view
modelu (presentation modelu, chcete-li) u každé stránky ve WP7 aplikaci.
&lt;/p&gt;
&lt;p&gt;
Dnes si ukážeme bázovou třídu pro view modely a další podpůrné třídy se službami,
která nás svou spoluprací zbaví nutnosti při psaní každé stránky myslet na to, že
autoři WP7 aplikací se vyžívají v recidivě nekrofilního chování u WP7 aplikací. Drahý
bratr Sigmund Freud by se po prohlídce stavového automatu “tombstonované“ aplikace
od architektů WP7 na své pohovce jistě tetelil radostí nad předaným šokujícím materiálem. &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-II_A042/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
Nejdříve si ale navrhneme minimální množinu vlastností, kterou by měl každý view model
splňovat, abychom se již nemuseli životním cyklem WP7 aplikace příliš zabývat při
návrhu každé stránky.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Musíme být schopni nahrát data při vytvoření nového view modulu. Také bychom měli
zajistit, že když dojde k “tombstoningu” aplikace ještě před získáním všech dat, nezůstane
view model v nějakém nekonzistentním stavu s třetinou nahraných dat, ale po obnovení
z “tombstoningu” dostane šanci nahrát data znovu. 
&lt;br&gt;
&lt;br&gt;
&lt;script src="https://gist.github.com/744974.js"&gt; &lt;/script&gt;
&lt;li&gt;
Budeme schopni při “tombstoningu” automaticky perzistovat dočasný stav každého view
modelu. Od této chvíle začneme říkat dočasnému stavu stav tranzientní.&lt;em&gt; V tomto
článku se zabývám jen tranzientním stavem aplikace, o perzistování “trvanlivějších”
dat do “isolated storage” se pobavíme v některém z dalších článků.&lt;/em&gt;
&lt;br&gt;
&lt;li&gt;
Po obnovení aplikace z “tombstonovaného” stavu každý view model automaticky nahraje
svůj tranzientní stav.&lt;br&gt;
Pro uložení a nahrání tranzientního stavu nadefinujeme rozhrani ITransientStateManager.&lt;br&gt;
&lt;br&gt;
&lt;script src="https://gist.github.com/744980.js"&gt; &lt;/script&gt;
&lt;li&gt;
Měli bychom dát šanci view modelům zareagovat na to, že stránka, ke které jsou přidruženy,
se stala aktivní stránkou, i na to, že k nim přidružená stránka aktivní už není, ať
už proto, že došlo k “tombstoningu” nebo uživatel přešel na jinou stránku v aplikaci.&lt;br&gt;
Pro tyto účely máme rozhraní IActivated a IDeactivated.&lt;br&gt;
&lt;br&gt;
&lt;script src="https://gist.github.com/744991.js"&gt; &lt;/script&gt;
&lt;li&gt;
Budeme mít sice bázovou třídu pro view modely, ale její použití si nebudeme vynucovat.
View model může být v aplikaci kterákoli třída. I když tato třída nebude potomkem
bázové třídy pro view modely, bude moci volitelně využít většinu služeb, které jsou
popsány v přechozích bodech.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Jedná se o view modely, měli bychom tedy na úrovní bázové třídy podporovat rozhraní
INotifyPropertyChanged, které nám dovoluje notifikovat o změně hodnoty ve vlastnostech
view modelu. Rozhraní INotifyPropertyChanged je ve WPF i v Silverlight aplikacích
všudypřítomné, proto si navrhneme další bázovou třídu PropertyChangedBase, která nám
kromě implementace rozhraní INotifyPropertyChanged přinese další užitečné služby.&lt;br&gt;
&lt;script src="https://gist.github.com/745001.js"&gt; &lt;/script&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Jaké další užitečné služby má třída PropertyChangedBase?
&lt;/p&gt;
&lt;p&gt;
Nemusíme vyvolávat událost PropertyChanged zadáním jen zadáním názvu vlastnosti (&lt;em&gt;RaisePropertyChanged(“UserName”)&lt;/em&gt;),
což může vést k chybě za běhu aplikace, když uděláme překlep v názvu vlastnosti (&lt;em&gt;(RaisePropertyChanged(“UseName”)&lt;/em&gt;),
ale můžeme předat název vlastnosti ve formě lambda výrazu, jehož syntaxe je zkontrolována
již kompilátorem. K tomu nám slouží metoda &lt;em&gt;RaisePropertyChangedEvent&lt;treturn&gt;
(Expression&lt;func&gt;
&lt;treturn&gt;
&amp;gt; propertyDefinition)
&lt;/em&gt;. Potomci třídy PropertyChangedBase mohou o změně hodnoty vlastnosti informovat
takto:
&lt;/p&gt;
&lt;script src="https://gist.github.com/745018.js"&gt; &lt;/script&gt;
&lt;p&gt;
U potomků třídy PropertyChangedBase, kterými budou i naše view modely, si můžeme také
zavoláním metody &lt;em&gt;RaiseAllPropertiesChanged&lt;/em&gt; vynutit vyvolání události o změně
hodnoty pro každou vlastnost. Další metodě s názvem &lt;em&gt;RaisePropertiesChanged(params
string[] properties) &lt;/em&gt;můžeme předat názvy vlastností, pro které má být vyvolána
metoda PropertyChanged.
&lt;/p&gt;
&lt;p&gt;
A teď si&amp;nbsp; již můžeme vytvořit slibovanou třídu ViewModelBase, která je potomkem
třídy PropertyChangedBase a podporuje všechna rozhraní zmíněná dříve.
&lt;/p&gt;
&lt;script src="https://gist.github.com/745046.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
V konstruktoru třída ViewModelBase přijímá titulek zobrazované stránky, který je uložen
do vlastnosti PageTitle.
&lt;/p&gt;
&lt;script src="https://gist.github.com/745079.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metoda Init z rozhraní Initialize by měla být volána vždy, když je view model vytvořen,
nebo když je po obnovení aplikace z “tombstonovaného” stavu zřejmé, že view model
nenahrál všechna data, což se zjistí voláním virtuální metody &lt;em&gt;IsAllInitDataLoaded&lt;/em&gt;,
která v této abstraktní třídě vždy&amp;nbsp; vrací true a čeká na to, až odvozené konkrétní
view modely dosadí svou logiku, kdy je považován view model za nahraný. Metoda Init
by měla být taky volána, když odvozený view model obnovená tranzientní data považuje
za špatná / zastaralá a nemůže je používat, což nám dá najevo nastavením vlastnosti &lt;em&gt;IsInvalidModel&lt;/em&gt; na
true. K rychlému zjištění, jestli&amp;nbsp; je možné view model dále používat slouží derivovaná
vlastnost &lt;em&gt;CanUseModel&lt;/em&gt;, která spojuje logiku obsaženou ve vlastnosti &lt;em&gt;IsInvalidModel&lt;/em&gt; a
metodě &lt;em&gt;IsAllInitDataLoaded.&lt;/em&gt;
&lt;/p&gt;
&lt;script src="https://gist.github.com/745094.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;Initialize.Init&lt;/em&gt; 
&lt;/p&gt;
&lt;script src="https://gist.github.com/745104.js"&gt; &lt;/script&gt;
&lt;p&gt;
V metodě &lt;em&gt;Init&lt;/em&gt; nejdříve nastavíme vlastnost &lt;em&gt;IsInvalidModel&lt;/em&gt; na true,
protože naše metoda &lt;em&gt;Init&lt;/em&gt; probíhá a kdyby došlo k “tombstoningu”, nemáme všechna
data a je potřeba volat metodu &lt;em&gt;Init&lt;/em&gt; znovu. Poté jen načteme titulek aplikace
do vlastnosti &lt;em&gt;AppTitle&lt;/em&gt;,&amp;nbsp; inicializujeme vlastnost &lt;em&gt;SuppressValidating&lt;/em&gt;,
která slouží k dočasnému potlačení ověřování platnosti data zadaných uživatelem ve
view modelu, na hodnotu false. &lt;em&gt;O vlastnosti SuppressValidating budeme více mluvit
v dalším článku včetně vysvětlení významu metody ValidateData a vlastnosti HasValidData. 
&lt;br&gt;
&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Dále &lt;em&gt;ViewModelBase&lt;/em&gt; nastavením vlastnosti &lt;em&gt;IsInvalidModel&lt;/em&gt; na false
sděluje, že jeho inicializace proběhla, všechna data v modelu považuje za platná a
dá šanci odvozeným třídám, aby inicializovaly svá data voláním chráněné virtuální
metody &lt;em&gt;DoInternalInit&lt;/em&gt;, která má ve &lt;em&gt;ViewModelBase&lt;/em&gt; prázdnou implementaci
a do které odvozené třídy dají svou specifickou logiku pro načtení dat. Vlastnost &lt;em&gt;IsInvalidModel&lt;/em&gt; mohou
samozřejmě odvozené třídy nastavit v metodě &lt;em&gt;DoInternalInit&lt;/em&gt; opět na true,
ale my ve vlastnosti &lt;em&gt;IsInvalidModel&lt;/em&gt; hodnotu true nenecháváme, protože si
přepsání metody &lt;em&gt;DoInternalInit&lt;/em&gt; v odvozených třídách nevynucujeme a v bázové
třídě ViewModelBase nemůžeme vědět, kdy odvozené třídy považují svá data za neplatná.
&lt;/p&gt;
&lt;p&gt;
V metodě &lt;strong&gt;Init &lt;/strong&gt;nakonec také voláním metody další chráněné virtuální
metody s názvem &lt;em&gt;DoInternalAsyncInit&lt;/em&gt; v &lt;strong&gt;samostatném vlákně &lt;/strong&gt;šanci
odvozeným třídám &lt;strong&gt;asynchronně &lt;/strong&gt;inicializovat svá data. Metodu &lt;em&gt;DoInternalAsyncInit&lt;/em&gt; by
měly odvozené třídy používat k časově náročné inicializaci, kterou není vhodné vhodné
dávat do synchronně&amp;nbsp; volané metody DoInternalInit a blokovat tak hlavní thread
aplikace.
&lt;/p&gt;
&lt;p&gt;
Mohlo by vás také zaujmout, že v sekci catch má speciální zacházení výjimka &lt;em&gt;ThreadAbortException
– &lt;/em&gt;tato výjimka není propagována výše, protože ji vyvolá samotné běhové prostředí
Silverlightu při násilném “tombstoningu”, jak jsem poznamenal na začátku tohoto článku.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Rozhraní &lt;em&gt;IActivated&lt;/em&gt; s metodou &lt;strong&gt;Activate &lt;/strong&gt;a&lt;strong&gt; &lt;/strong&gt;rozhraní&lt;strong&gt; &lt;/strong&gt;&lt;em&gt;IDeactivated &lt;/em&gt;s
metodou &lt;strong&gt;Deactivate&lt;/strong&gt; ve &lt;em&gt;ViewModelBase&lt;/em&gt; mají jen prázdnou implementaci
a čekají na to, jakou logiku do nich vloží odvozené třídy. Mimochodem&amp;nbsp; – na tomto
místě bychom měli poprvé vytušit, že budeme potřebovat “hostitele” našich view modelů,
který bude vědět, kdy volat metody &lt;em&gt;Activate&lt;/em&gt;, &lt;em&gt;Deactivate&lt;/em&gt;, &lt;em&gt;Init&lt;/em&gt; a
další.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
Třída ViewModelBase explicitně implementuje rozhraní &lt;em&gt;ITransientStateManager&lt;/em&gt;,
které jsme si zavedli pro podporu automatického ukládání a nahrávání tranzientního
stavu. Metody &lt;em&gt;LoadState&lt;/em&gt; a &lt;em&gt;SaveState&lt;/em&gt; ale po svém vyvolání jen předají
řízení chráněným virtuálním metodám &lt;em&gt;DoInternalLoadTransientState&lt;/em&gt; a &lt;em&gt;DoInternalSaveTransientState, &lt;/em&gt;aby
dali šanci i odvozeným třídám změnit způsob uložení a nahrání tranzientního stavu,
i když odvozené třídy jsou většinou spokojeni s tím, že to za ně zvládne předek ViewModelBase.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;script src="https://gist.github.com/745208.js"&gt; &lt;/script&gt;
&lt;p&gt;
Třída ViewModelBase ve svém statickém konstruktoru dosazuje výchozí objekt podporující
rozhraní &lt;em&gt;ITransientStateHelper&lt;/em&gt;, které je klíčové pro uložení a obnovení tranzientního
stavu view modelů a na které delegují i metody &lt;em&gt;DoInternalLoadTransientState&lt;/em&gt;&amp;nbsp;
a &lt;em&gt;DoInternalSaveTransientState&lt;/em&gt; v předchozím výpisu.
&lt;/p&gt;
&lt;p&gt;
Všimněte si, že metoda &lt;em&gt;DoInternalLoadTransientState &lt;/em&gt;po obnovení tranzientního
stavu zkontroluje, jestli se dá view model používat, a pokud ne, zavolá i v této fázi
metodu Init.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;if (!CanUseModel)&lt;br&gt;
{&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&amp;nbsp; Init();&lt;br&gt;
}&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
A nyní se podíváme na mocné rozhraní &lt;em&gt;ITransientStateHelper&lt;/em&gt;
&lt;/p&gt;
&lt;strong&gt;&lt;/strong&gt;&lt;script src="https://gist.github.com/745212.js"&gt; &lt;/script&gt;
&lt;p&gt;
Je asi zřejmé, že metoda &lt;em&gt;GetTransientState&lt;/em&gt; vrátí v objektu Dictionary tranzientní
stav objektu, který jí byl předán v argumentu obj. Metoda &lt;em&gt;RestoreTransientState&lt;/em&gt; naopak
obnoví tranzientní stav objektu v argumentu obj hodnotami v argumentu savedState.
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;IsTransientStateEnabledForObject&lt;/em&gt; zjistí, jestli je možné z předaného
objektu získat tranzientní stav. Jak uvidíme, odvozené view modely mohou odmítnout
uložení tranzientního stavu a kdekoli v aplikaci&amp;nbsp; můžeme jejich rozhodnutí jednoduše
zjistit předáním instance view modelu této metodě.
&lt;/p&gt;
&lt;p&gt;
Zde je jedna z možných realizací rozhraní IStateTransientStateHelper, kterou používá
i naše třída ViewModelBase.
&lt;/p&gt;
&lt;script src="https://gist.github.com/745247.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Odpovědnosti metod &lt;em&gt;GetTransientState&lt;/em&gt; a &lt;em&gt;RestoreTransientState&lt;/em&gt; jsem
již popsal, nyní jen zmíním pár specialitek v kódu třídy TransientStateHelper.
&lt;/p&gt;
&lt;p&gt;
Metoda GetTransientState zjistí, jestli předaný objekt&amp;nbsp; má tranzientní stav tak,
že zavolá metodu &lt;strong&gt;IsTransientStateEnabledForObject(obj)&lt;em&gt;.&lt;/em&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Metoda IsTransientStateEnabledForObject kontroluje, jestli třída, ze které objekt
pochází, nezakázala vydání tranzientního stavu tím, že je na ní aplikován atribut
[NonTransientState].
&lt;/p&gt;
&lt;p&gt;
Atribut NonTransientState
&lt;/p&gt;
&lt;script src="https://gist.github.com/745279.js"&gt; &lt;/script&gt;
&lt;p&gt;
Atribut NonTransientState může být aplikován nejen na celou třídu, ale i na jednotlivé
vlastnosti objektu, které nemají být součástí tranzientního stavu.&amp;nbsp; &lt;strong&gt;Metoda
GetTransientState neukládá celé view modely, ale s využitím reflexe jen hodnoty jejich
vlastností. Atribut NonTransientState dovoluje vyřadit vlastnosti, které v tranzientním
stavu view modelu nemají co dělat.&lt;/strong&gt; To ale není vše – přímo metoda GetTransientState
dle jmenné konvence vyřadí všechny vlastnosti, jejichž suffix je v poli IGNORE_METHOD_SUFFIX_LIST 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;public static readonly IEnumerable&lt;string&gt;
IGNORE_METHOD_SUFFIX_LIST = new[] { "Command", "Action", "Helper", "Service", "SynchContext"};
&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Do tranzientního stavu se tak nedostanou ve view modelech se často nacházející, ale
s tranzientním stavem view modelu nic nemající a navíc většinou neserializovatelné
objekty jako jsou objekty ICommand (vlastnost Select&lt;strong&gt;Command&lt;/strong&gt;, Save&lt;strong&gt;Command&lt;/strong&gt;),
delegáti&amp;nbsp; TextboxTextChanged&lt;strong&gt;Action&lt;/strong&gt;, služby (ILogger&lt;strong&gt;Service&lt;/strong&gt;)
a další.
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;RestoreTransientState&lt;/em&gt; obnoví tranzientní stav objektu. Za zmínku stojí,
že když je předaný objekt potomkem PropertyNotificationBase, tak nastavením vlastnosti
notificationBase.SuppressPropertyChangedNotification na true potlačíme dočasně vyvolání
události OnPropertyChanged, protože je vhodné, abychom událost nevyvolávali, když
view model neobsahuje všechna data a nevíme, kdo všechno na událost reaguje a jaká
další, nyní ve view modelu se nenacházející data, by chtěl načíst. Jak jsem ale psal
v požadavcích na začátku článku, view model nemusí podporovat žádná rozhraní, nemusí
být potomkem ViewModelBase ani PropertyNotificationBase, a proto si ani dědění z PropertyNotificationBase
v této metodě nevynucujeme. Poté, co metoda &lt;em&gt;RestoreTransientState &lt;/em&gt;obnoví
hodnoty všech vlastností, má TransientStateHelper povinnost notifikovat okolí o změně
hodnot všech vlastností view modelu. Jestliže je objekt s obnoveným tranzientním stavem
potomkem PropertyNotificationBase, zavoláme metodu RaisePropertiesChanged(propertyNames.ToArray()),
jinak se metoda &lt;em&gt;RestoreTransientState&lt;/em&gt; pokusí dohledat opět za pomoci reflexe
na objektu metodu nazvanou RaisePropertyChangedEvent, která přijímá název vlastnosti
a kterou použije pro hromadnou distribuci událostí OnPropertyChanged.
&lt;/p&gt;
&lt;p&gt;
Ovládací prvky obsažené (nejen) v control toolkitu jsou&amp;nbsp; přecitlivělé na pořadí
vyvolávání události, a proto jsou vlastnosti seřazeny nyní tak, aby vlastnosti začínající
slovem &lt;em&gt;Selected&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;vyvolávaly událost OnPropertyChanged jako
poslední. Máte-li ve view modelu kolekci nazvanou Orders (všechny objednávky) a SelectedOrder
(vybraná objednávka z této kolekce), je zaručeno, že &lt;strong&gt;událost OnPropertyChanged
pro vlastnost SelectedOrder bude vyvolána až po události OnPropertyChanged pro vlastnost
Orders.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Prefixy vlastností, které mají vyvolávat události jako poslední, jsou v proměnné
LAST_SET_VALUE_METHOD_PREFIX. Tyto vlastnosti jsou označeny příznakem LastInit z enumerace
PropertyType.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;public static readonly IEnumerable&lt;string&gt;
LAST_SET_VALUE_METHOD_PREFIX = new[] { "Selected" };
&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
To by pro dnešek k třídě ViewModelBase a jejím pomocníkům stačilo:
&lt;/p&gt;
&lt;p&gt;
Příště se podíváme hlavně na “hostitele” view modelů, který by měl být schopen:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Volat na view modelech ve “správnou dobu” metody Init, LoadState, SaveState, Activate,
Deactivate. 
&lt;br&gt;
&lt;li&gt;
Připojit view modely k view (stránce).&lt;br&gt;
&lt;li&gt;
Náš hostitel bude podporovat i více view modelů na jedné stránce, včetně “dědění”
a sdílení použitých view modelů mezi různými view na stránce.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
A také si příště vysvětlíme, proč při získání tranzientního stavu ve ViewModelbase
místo objektu Dictionary používáme vlastní třídu KnownTypesDictionary. Jak možná tušíte,
i název “KnownTypes” odkazuje k tomu, že mají-li být hodnoty uložené v tranzientním
stavu serializovatelné, tak &lt;em&gt;DataContractSerializer,&lt;/em&gt; používaný infrastrukturou
WP7 k serializaci tranzientního stavu, musíme přesvědčit, že v objektu Dictionary
jsou jen objekty z jemu “známých” tříd.
&lt;/p&gt;
&lt;p&gt;
Předcházející články:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;Tipy
pro Windows Phone 7 aplikace I&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=060fbd09-0368-4733-92ad-aaecf48409a4" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,060fbd09-0368-4733-92ad-aaecf48409a4.aspx</comments>
      <category>C#</category>
      <category>Compact .Net Framework</category>
      <category>Návrhové vzory</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=eb87dd26-6375-4362-abfc-2fd0b13fca84</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,eb87dd26-6375-4362-abfc-2fd0b13fca84.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,eb87dd26-6375-4362-abfc-2fd0b13fca84.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=eb87dd26-6375-4362-abfc-2fd0b13fca84</wfw:commentRss>
      <title>Pozv&amp;aacute;nka na m&amp;eacute; kurzy OOP, UML a n&amp;aacute;vrhov&amp;yacute;ch vzorů a odpovědi na někter&amp;eacute; dotazy zaslan&amp;eacute; emailem - podzim 2010</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,eb87dd26-6375-4362-abfc-2fd0b13fca84.aspx</guid>
      <link>http://blog.renestein.net/Pozvaacutenka+Na+Meacute+Kurzy+OOP+UML+A+Naacutevrhovyacutech+Vzor%c5%af+A+Odpov%c4%9bdi+Na+N%c4%9bktereacute+Dotazy+Zaslaneacute+Emailem+Podzim+2010.aspx</link>
      <pubDate>Sat, 18 Sep 2010 09:17:31 GMT</pubDate>
      <description>Opět bych Vás všechny rád  pozval na pravidelný podzimní běh kurzů Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací 1 a Pokročilé návrhové vzory a objektové principy 2. Níže také naleznete odpovědi na pravidelně se opakující dotazy v emailech. 
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=eb87dd26-6375-4362-abfc-2fd0b13fca84"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,eb87dd26-6375-4362-abfc-2fd0b13fca84.aspx</comments>
      <category>Analytické drobky</category>
      <category>Kurzy UML a OOP</category>
      <category>Návrhové vzory</category>
      <category>UML</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=cd84ce22-c766-49cc-ace9-f003bdb104e2</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,cd84ce22-c766-49cc-ace9-f003bdb104e2.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,cd84ce22-c766-49cc-ace9-f003bdb104e2.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=cd84ce22-c766-49cc-ace9-f003bdb104e2</wfw:commentRss>
      <title>Pozv&amp;aacute;nka na kurz Objektov&amp;yacute;mi principy a n&amp;aacute;vrhov&amp;yacute;mi vzory ř&amp;iacute;zen&amp;yacute; design a v&amp;yacute;voj kvalitn&amp;iacute;ch aplikac&amp;iacute; 1 &amp;ndash; jaro 2010</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,cd84ce22-c766-49cc-ace9-f003bdb104e2.aspx</guid>
      <link>http://blog.renestein.net/Pozvaacutenka+Na+Kurz+Objektovyacutemi+Principy+A+Naacutevrhovyacutemi+Vzory+%c5%98iacutezenyacute+Design+A+Vyacutevoj+Kvalitniacutech+Aplikaciacute+1+Ndash+Jaro+2010.aspx</link>
      <pubDate>Wed, 07 Apr 2010 11:48:36 GMT</pubDate>
      <description>Rád bych Vás pozval na další běh kurzu Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací 1. Pokud se někdo z Vás (oprávněně) diví, proč tak pozdě a proč Vás nezvu i na kurz OOP 2, níže v tomto spotu nalezne odpovědi. &lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=cd84ce22-c766-49cc-ace9-f003bdb104e2"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,cd84ce22-c766-49cc-ace9-f003bdb104e2.aspx</comments>
      <category>Analytické drobky</category>
      <category>Kurzy UML a OOP</category>
      <category>Návrhové vzory</category>
      <category>UML</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=d28b9cd9-bf78-4e1f-8407-3a213baad863</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,d28b9cd9-bf78-4e1f-8407-3a213baad863.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,d28b9cd9-bf78-4e1f-8407-3a213baad863.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=d28b9cd9-bf78-4e1f-8407-3a213baad863</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <title>V&amp;yacute;hody a nev&amp;yacute;hody softwarov&amp;yacute;ch tov&amp;aacute;ren</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,d28b9cd9-bf78-4e1f-8407-3a213baad863.aspx</guid>
      <link>http://blog.renestein.net/Vyacutehody+A+Nevyacutehody+Softwarovyacutech+Tovaacuteren.aspx</link>
      <pubDate>Sun, 21 Mar 2010 10:57:10 GMT</pubDate>
      <description>Emailem jsem dostal zajímavou otázku, jaký je můj názor na softwarové továrny a kde vidím výhody a nevýhody softwarových továren. Odpověď nakonec publikuji i zde – už jen proto, že jsem si při jejím psaní uvědomil, že na továrnu kladu stejné nároky jako na kteroukoli další knihovnu v systému a že výběr softwarové továrny se u mě moc neliší od výběru třeba ORM Frameworku. Nejde o taxativní výčet výhod a nevýhod, ale spíš o volně nahozená témata, která mě za 20 minut psaní příspěvku napadla. &lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=d28b9cd9-bf78-4e1f-8407-3a213baad863"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,d28b9cd9-bf78-4e1f-8407-3a213baad863.aspx</comments>
      <category>.NET Framework</category>
      <category>Analytické drobky</category>
      <category>Návrhové vzory</category>
      <category>UML</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=24bbfc33-2595-43c9-a9a2-1df1de6a9b30</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,24bbfc33-2595-43c9-a9a2-1df1de6a9b30.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,24bbfc33-2595-43c9-a9a2-1df1de6a9b30.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=24bbfc33-2595-43c9-a9a2-1df1de6a9b30</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <title>Hr&amp;aacute;tky s Reaktivn&amp;iacute;m frameworkem (RX extenze)</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,24bbfc33-2595-43c9-a9a2-1df1de6a9b30.aspx</guid>
      <link>http://blog.renestein.net/Hraacutetky+S+Reaktivniacutem+Frameworkem+RX+Extenze.aspx</link>
      <pubDate>Tue, 02 Feb 2010 06:43:00 GMT</pubDate>
      <description>Zkusme se nyní podívat, jak by nám s “převrácením starších asynchronních metod z hlavy zpět na synchronní nohy” mohl pomoci RX Framework. Úplné základy v tomto článku nezazní a začátečníky odkazuji na sérii přednášek na Channel 9, kde dozvíte i zajímavé podrobnosti o genezi celého RX Frameworku  a matematické dualitě rozhraní IEnumerable a IObservable (jinými slovy o společných rysech dobře známých GoF návrhových vzorů Iterátor a Observer). &lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=24bbfc33-2595-43c9-a9a2-1df1de6a9b30"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,24bbfc33-2595-43c9-a9a2-1df1de6a9b30.aspx</comments>
      <category>.NET Framework</category>
      <category>C# Posterous API</category>
      <category>LINQ</category>
      <category>Návrhové vzory</category>
      <category>RX Extensions</category>
      <category>Windows Forms</category>
    </item>
  </channel>
</rss>