<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>.NET/C# development blog</title>
	<atom:link href="http://blog.milosierny.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.milosierny.net</link>
	<description>blog o technologiach okołodotnetowych</description>
	<lastBuildDate>Sat, 24 Apr 2010 20:17:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Aplikacje dla Microsoft Mediaroom</title>
		<link>http://blog.milosierny.net/2010/04/24/aplikacje-dla-microsoft-mediaroom/</link>
		<comments>http://blog.milosierny.net/2010/04/24/aplikacje-dla-microsoft-mediaroom/#comments</comments>
		<pubDate>Sat, 24 Apr 2010 20:17:52 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[iptv]]></category>
		<category><![CDATA[mediaroom]]></category>

		<guid isPermaLink="false">http://blog.milosierny.net/?p=120</guid>
		<description><![CDATA[Jak wyglądają aplikacje zaprojektowanie dla telewizji interaktywnych?
Można je zobaczyć między innymi tutaj.
]]></description>
			<content:encoded><![CDATA[<p>Jak wyglądają aplikacje zaprojektowanie dla telewizji interaktywnych?<br />
Można je zobaczyć między innymi <a href="http://www.microsoft.com/Mediaroom/Themes/applications.aspx">tutaj</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2010/04/24/aplikacje-dla-microsoft-mediaroom/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Na czym polega podpisywanie assembly?</title>
		<link>http://blog.milosierny.net/2010/03/18/na-czym-polega-podpisywanie-assembly/</link>
		<comments>http://blog.milosierny.net/2010/03/18/na-czym-polega-podpisywanie-assembly/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 17:49:35 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[GAC]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://blog.milosierny.net/?p=107</guid>
		<description><![CDATA[Większość programistów podczas nauki programowania na platformie .NET omija temat silnych nazw i podpisywania assembly – nic dziwnego, kwestie te nie są najistotniejsze na etapie eksperymentowania z .NETem.
W komercyjnych, profesjonalnych albo bardziej zaawansowanych projektach kwestie te zyskują na znaczeniu. W tym wpisie zajmę się tematyką związaną z Global Assembly Cache, podpisywaniem podzespołów (polska nazwa assembly) [...]]]></description>
			<content:encoded><![CDATA[<p>Większość programistów podczas nauki programowania na platformie .NET omija temat silnych nazw i podpisywania assembly – nic dziwnego, kwestie te nie są najistotniejsze na etapie eksperymentowania z .NETem.<br />
W komercyjnych, profesjonalnych albo bardziej zaawansowanych projektach kwestie te zyskują na znaczeniu. W tym wpisie zajmę się tematyką związaną z <em>Global Assembly Cache</em>, podpisywaniem podzespołów (polska nazwa <em>assembly</em>) i silnymi nazwami.<br />
<script type="text/javascript"><!--
google_ad_client = "pub-0055460474580388";
/* 468x60, utworzono 09-11-27 */
google_ad_slot = "0413534588";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h1>Po co podpisywać assembly?</h1>
<p>Zasadnicza odpowiedź na to pytanie jest prosta: z tych samych powodów, dla których podpisuje się cokolwiek innego. Jeśli podpiszesz swoim kluczem prywatnym wiadomość email, odbiorca będzie mógł sprawdzić, że email rzeczywiście pochodzi od Ciebie; jeśli podpiszesz plik cyfrowo, będziesz mógł sprawdzić, czy nikt nie zmienił jego treści.</p>
<p>Między innymi z tych powodów stosuje się podpisywanie assembly – żeby potwierdzić tożsamość podzespołu.</p>
<p>Pełna tożsamość assembly składa się z 4 części:</p>
<ul>
<li>krótkiej nazwy. Na platformie Windows jest to nazwa pliku bez rozszerzenia, np.:  Microsoft.DirectX.Direct3D;</li>
<li>kultury, czyli wersji lokalizacyjnej, np.: en;</li>
<li>tokena publicznego klucza podpisu: np.: 31bf3856ad364e35;</li>
<li>wersji np:  1.0.2902.0.</li>
</ul>
<p>lub  w postaci jednego łańcucha:</p>
<pre>Microsoft.DirectX.Direct3D, Culture=en, 
PublicKeyToken=31bf3856ad364e35, Version=1.0.2902.0</pre>
<p>Dopóki nie podpiszesz swojego podezspołu, część PublicKeyToken pozostaje pusta.</p>
<p>Zmiana wartości jednej z tych 4 części skutkuje zmianą tożsamości biblioteki/assembly. Taki sposób identyfikacji bibliotek rozwiązał stary problem <em>DLL Hell</em>, który polegał na tym, że nowe instalacje nadpisywały starsze wersje jakiejś współdzielonej biblioteki, a wcześniej zainstalowane programy odwoływały się do tej nowej biblioteki próbując wykonać operacji, której implementacja się zmieniła w nowej wersji. Skutkował oto błędnym działaniem programów a czasami i systemu operacyjnego.</p>
<p>.NET Framework częściowo rozwiązuje ten problem za pomocą GAC (Global Assembly Cache), gdzie różne wersje tych samych współdzielonych bibliotek mogą być przechowywane bez przeszkód. Jak zatem .NE T rozróżnia rozmaite wersje bibilotek (np. DirectX for Managed Code)? Ano właśnie za pomocą tych 4-częściowych nazw.</p>
<p>Żeby jednak biblioteka (podzespół) mogła być umieszczona w GAC musi mieć silną nazwę.</p>
<h1>Silna nazwa podzespołu &#8211; Assembly Strong Name</h1>
<p>Silna nazwa (<em>strong name</em>) to owa 4-częściowa nazwa, która zawiera <em>PublicKeyToken </em>plus cyfrowy podpis. Jak powstaje ten podpis?</p>
<p>Żeby go utworzyć potrzeba pary kluczy (publiczny-prywatny) o długości 1024-bitów.  Klucz publiczny jest dołączany do 4-częściowej nazwy podzespołu właśnie jako <em>PublicKeyToken</em>. Taka komplementarna para jest wykorzystywana do szyfrowania za pomocą algorytmu <a href="http://pl.wikipedia.org/wiki/RSA_(kryptografia)">RSA</a>.</p>
<p>Kiedy kompilator jest proszony o cyfrowe podpisanie podzespołu, najpierw oblicza skrót z jego zawartości za pomocą funkcji haszującej. Później ten skrót jest szyfrowany kluczem prywatnym pochodzącym z pary kluczy i umieszczany w podzespole.</p>
<p>Tak powstaje podpisany podzespół z silną nazwą.</p>
<p>Kiedy później zachodzi potrzeba zweryfikować tożsamość danego podzespołu (mówiąc wprost: sprawdzić, czy nikt w nim nie grzebał), wykonywane są następujące kroki:</p>
<ul>
<li>liczony jest skrót z zawartości podzespołu;</li>
<li>wyłuskiwany jest publiczny klucz (zapisany w podzespole);</li>
<li>klucz ten jest używany do rozszyfrowania skrótu podzespołu utworzonego podczas kompilacji;</li>
<li>oba skróty (ten z kompilacji i ten wyliczony w kroku pierwszym) są porównywane;</li>
<li>jeśli nie są równe znaczy to, że zawartość podzespołu została zmieniona.</li>
</ul>
<h1>Jak utworzyć silną nazwę i podpisać assembly?</h1>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1371px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Można to zrobić na kilka sposobów, np. za pomocą Visual Studio lub narzędzia linii komend sn.exe.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1371px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Omówię pierwszy sposób.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 1371px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Wybieramy ustawienia naszego projektu (prawy przycisk na nazwie projektu -&gt; Properties) i przechodzimy do zakładki Signing. Zaznaczamy opcję Sign the assembly.</div>
<p>Można to zrobić na kilka sposobów, np. za pomocą Visual Studio lub narzędzia linii komend sn.exe.</p>
<p>Omówię pierwszy sposób.</p>
<p>Wybieramy ustawienia naszego projektu (prawy przycisk na nazwie projektu &gt; <em>Properties</em>) i przechodzimy do zakładki <em>Signing</em>. Zaznaczamy opcję <em>Sign the assembly.</em></p>
<p><em> </em></p>
<div id="attachment_110" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-110" title="Podpisywanie1" src="http://blog.milosierny.net/wp-content/uploads/2010/03/signing1-300x207.png" alt="Podpisywanie podzespołu" width="300" height="207" /><p class="wp-caption-text">Podpisywanie podzespołu</p></div>
<p class="MsoNormal"><span lang="PL">Możemy skorzystać z istniejącego pliku z kluczami, bądź utworzyć nowy. Stwórzmy nowy:</span></p>
<p class="MsoNormal"><span lang="PL"> </span></p>
<div id="attachment_111" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-111" title="signing2" src="http://blog.milosierny.net/wp-content/uploads/2010/03/signing2-300x185.png" alt="Podpisywanie podzespołu" width="300" height="185" /><p class="wp-caption-text">Podpisywanie podzespołu - tworzenie klucza</p></div>
<p class="MsoNormal"><span lang="PL">Wpisujemy nazwę i hasło, które będzie chroniło nasze klucze przed niepowołanym dostępem.</span></p>
<p class="MsoNormal"><span lang="PL">Klikamy OK., zapisujemy projekt i kompilujemy. I już mamy podpisany podzespół z silną nazwą. Wygenerowany plik z kluczami zachowujemy do późniejszego użycia.</span></p>
<p class="MsoNormal"><span lang="PL">Jak zweryfikować, czy nasz podzespół ma poprawną tożsamość? Możemy użyć narzędzia <em>sn.exe</em> z opcją <em>–v</em>. Opcja <em>–T </em>wyświetla publiczny token.</span></p>
<p class="MsoNormal"><span lang="PL"> </span></p>
<div id="attachment_112" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-112" title="signing3" src="http://blog.milosierny.net/wp-content/uploads/2010/03/signing3-300x148.png" alt="Sprawdzanie podpisu" width="300" height="148" /><p class="wp-caption-text">Sprawdzanie podpisu</p></div>
<h1>Global Assembly Cache</h1>
<p>Jak wspomniałem GAC &#8211; <em>Global Assembly Cache</em> (globalna pamięć podręczna podzespołów) jest miejscem składowania współdzielonych bibliotek DLL używany przez programy na platformie .NET. Dzięki GAC możemy przestać martwić się o fizyczne położenie używanych przez nas bibliotek na dysku. Jeśli podzespół został dodany do GAC, CLR zawsze będzie w stanie go znaleźć i załadować. GAC rozwiązuje też słynny problem DLL hell (&#8221;<em>piekło DLL</em>&#8220;) – umożliwia przechowywanie na jednej maszynie dowolnej liczby wersji danej biblioteki.</p>
<p>Standardowo GAC znajduje się w katalogu <em>C:\Windows\Assembly\GAC</em>.</p>
<p>Podzespoły znajdujące się w GAC są traktowane jako bezpieczne. Aby rzeczywiście tak było, podczas instalacji podzespołu w GAC przeprowadzana jest weryfikacja jego cyfrowego podpisu. A więc w GACu mogą być umieszczone tylko podzespoły z silną nazwą.</p>
<p>Poza tym tylko użytkownicy z grup administratorzy i użytkownicy zaawansowani mogą dodawać podzespoły do GAC.</p>
<p>Dla każdego nowododanego podzespołu tworzony jest katalog o nazwie tożsamej z krótką nazwą podzespołu (np. <em>Microsoft.DirectX.Direct3D</em>) a w nim podkatalogi odpowiadające wersjom – nazwy są tworzone wg wzorca wersja__publiczny token (np. <em>1.0.2902.0__31bf3856ad364e35</em>).</p>
<p>Jak dodawać swoje podzespołu do GAC? Służy do tego narzędzie <em>GACUTIL.EXE</em><span style="mso-spacerun: yes;"> </span>(parametry /i i /il instalują podzespoły; parametry /u i /ul odinstalowują podzespoły)</p>
<h1>Jak bardzo jest to bezpieczne?</h1>
<p>Krótko mówiąc: nie bardzo. Zmiana zawartości podpisanego assembly nie uniemożliwia jego uruchomienia przez CLR. Można co prawda zweryfikować integralność pliku, ale nie można uniemożliwić jego uruchomienia, zwłaszcza na poziomie pełnego zaufania.</p>
<p>Jeśli chodzi o GAC to integralność podzespołu jest sprawdzana wyłącznie w momencie dodawania go do GACa. Później już nie jest. Osoba z uprawnieniami administratora może więc podmienić zweryfikowany podzespół na niezweryfikowany.</p>
<p>Co więcej, silną nazwę można usunąć lub zamienić, co zostało opisane w tym artykule.</p>
<p>Jak więc zabezpieczyć swój kod, tak żeby nie można było go uruchomić, gdy jego integralność została naruszona? Zajmę się tym w jednym z kolejnych wpisów.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2010/03/18/na-czym-polega-podpisywanie-assembly/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Egzamin 70-562: .NET Framework 3.5, ASP.NET Application Development – jak zdać?</title>
		<link>http://blog.milosierny.net/2009/12/16/egzamin-70-562-net-framework-3-5-asp-net-application-development-%e2%80%93-jak-zdac/</link>
		<comments>http://blog.milosierny.net/2009/12/16/egzamin-70-562-net-framework-3-5-asp-net-application-development-%e2%80%93-jak-zdac/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 21:53:43 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[70-562]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[certyfikacja]]></category>
		<category><![CDATA[egzamin]]></category>
		<category><![CDATA[mcts]]></category>

		<guid isPermaLink="false">http://blog.milosierny.net/?p=93</guid>
		<description><![CDATA[Ogólnie o 70-562
Celem egzaminu numer 70-562 jest potwierdzenie kompetencji w zakresie programowania aplikacji internetowych za pomocą ASP.NET na platformie .NET 3.5. Jak czytamy na stronie poświęconej egzaminowi profil idealnego kandydata do zdania tego egzaminu to osoba pracująca w średnich-dużych zespołach z dwu-, trzyletnim doświadczeniem w dziedzinie tworzenia aplikacji webowych.
Prócz tego egzamin obejmuje wszystkie zagadnienia dotykające [...]]]></description>
			<content:encoded><![CDATA[<h1>Ogólnie o 70-562</h1>
<p>Celem egzaminu numer 70-562 jest potwierdzenie kompetencji w zakresie programowania aplikacji internetowych za pomocą ASP.NET na platformie .NET 3.5. Jak czytamy na stronie poświęconej egzaminowi profil idealnego kandydata do zdania tego egzaminu to osoba pracująca w średnich-dużych zespołach z dwu-, trzyletnim doświadczeniem w dziedzinie tworzenia aplikacji webowych.</p>
<p>Prócz tego egzamin obejmuje wszystkie zagadnienia dotykające tematyki webaplikacji, między innymi:</p>
<ul>
<li>Dostęp do danych za pomocą ADO.NET</li>
<li>Webserwisy</li>
<li>WCF</li>
<li>AJAX i Javascript</li>
<li>Konfiguracja IIS.</li>
</ul>
<p>Zakres jest dość rozległy, ale nadal obraca się wokół pisania aplikacji internetowych i w tym kontekście sprawdza wiedzę z dodatkowych dziedzin.</p>
<p>Oczywiście – tak jak w przypadku innych egzaminów &#8211; samo kilkuletnie doświadczenie programistyczne nie gwarantuje pozytywnego złożenia egzaminu. Potrzebne jest jeszcze solidne powtórzenie swojej wiedzy i nauczenie się pewnych rzeczy na pamięć (co w codziennej pracy z powodzeniem jest zastępowane choćby przez Intellisense). Jak zatem dobrze przygotować się do złożenia egzaminu?</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-0055460474580388";
/* 468x60, utworzono 09-11-27 */
google_ad_slot = "0413534588";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h1>70-562 – jak zdać?</h1>
<p>Dobrą pomocą do powtórzenia materiału jest na przykład książka: <a href="http://www.microsoft.com/learning/en/us/book.aspx?ID=12489">MCTS Self-Paced Training Kit (Exam 70-562): Microsoft .NET Framework 3.5-ASP.NET Application Development</a>. Rozdział po rozdziale omawia  poszczególne zagadnienia, szczególnie dużo miejsca poświęcając ADO.NET. Trzeba zaznaczyć, że nie jest to książka do nauki programowania w ASP.NET  &#8211; można ją raczej nazwać repetytorium. Na uwagę zasługują ramki „Exam tip” z sugestiami, na co szczególnie zwrócić uwagę podczas egzaminu.</p>
<p>Książka na pierwszy rzut oka przeraża objętością – jest przynajmniej tak duża jak Self-Paced Training Kit dla egzaminu 70-536. Pamiętajmy jednak, że przykładowe kody źródłowe pisane są podwójnie (w C# i w VB.NET), a sporą cześć zajmują powtórki rozdziałów i przykładowe scenariusze.</p>
<p>Zasadniczo są dwa sposoby używania książki. Można próbować czytać ją tzw. ciurkiem i… po mniej więcej pół godziny odpłynąć do krainy Morfeusza. Nie polecam.</p>
<p>Drugi sposób – znacznie bardziej efektywny – to czytanie książki z otwartym Visual Studio i wypróbowywanie konstrukcji, o których właśnie czytasz. Oczywiście &#8211; pewnie większość z nich już kiedyś używałeś, ale być może nie zauważyłeś pewnych detali, które mogą zaważyć na tym, jak odpowiesz na pytania.</p>
<p>Olbrzymią wartością dodaną jest płyta z przykładowymi pytaniami testowymi. Jest 125 pytań podsumowujących poszczególne lekcje i 200 pytań praktycznych przypominających te, które będą na egzaminie.</p>
<p>W sieci można też kupić zestawy przykładowych pytań na <a href="http://www.measureup.com/">MeasureUp</a> lub na <a href="http://www.selftestsoftware.com/">SelfTestSoftware</a>, które także przypominają pytania na prawdziwym egzaminie i pozwalają ocenić stan przygotowania.</p>
<p>Tak na marginesie: w <a href="http://blog.milosierny.net/2009/01/21/egzamin-70-536-application-development-foundation/#comments">komentarzach</a> do wpisu o <a href="http://blog.milosierny.net/2009/01/21/egzamin-70-536-application-development-foundation/">egzaminie 70-536</a> użytkownik Matol napisał, że można kupić prawdziwe (lub zbliżone do prawdziwych) pytania z egzaminów albo nawet dostać je za darmo, w związku z czym &#8211; jego zdaniem &#8211; egzaminy te nie sprawdzają jakiejkolwiek rzeczywistej wiedzy. Z takim stwierdzeniem nie mogę się zgodzić (z wielu powodów). Jeśli natomiast Matol miał na myśli, że przez dumpy z pytań egzaminacyjnych wartość egzaminów się obniża, to owszem, skłonny jestem przyznać rację. Ale jednocześnie można powiedzieć, że również maturę i pracę magisterską można kupić (i także deprecjonuje to wartość tych egzaminów), a jednak nikt nie wyobraża sobie nie zrobić matury albo nie złożyć egzaminu magisterskiego. Tym niemniej Matol poczynił ciekawą uwagę i odniosę się do niej w innym wpisie.</p>
<p>Wracając do pytań testowych – oczywiście uczenie się odpowiedzi na pamięć nie ma najmniejszego sensu. Ale wykonywanie testów i sprawdzanie swoich odpowiedzi pozwala szybko zidentyfikować te obszary, w których nasza wiedza wymaga ulepszenia.</p>
<p>Ten model nauki sprawdził się w moim przypadku. Nie korzystałem z dumpów i nie mogę się pochwalić wynikiem 1000/1000, ale z powodzeniem zdałem egzamin. Oczywiście z powodu NDA nie mogę ujawniać treści egzaminu, ale zaskoczyła mnie minimalna liczba pytań dotycząca LINQ. Pozostałe proporcje były „w normie”.</p>
<p>Kilka podstawowych informacji dla osób, które jeszcze nie zdawały: egzamin pisze się w centrum szkoleniowym, które może organizować certyfikację Microsoft (<a href="http://www.microsoft.com/poland/certyfikacje/training/default.mspx">aktualna lista ośrodków</a>) za pomocą programu testującego na komputerze. Wynik zna się od razu po egzaminie. Do zaliczenia potrzeba 700 punktów na 1000 możliwych.</p>
<h1>70-562 – zdałem i co dalej?</h1>
<p>Jeśli planujesz przystąpić do egzaminu 70-562 raczej wątpię, że Twój wybór jest przypadkowy. Egzamin ten jest zwykle wybierany jako drugi, po zdaniu 70-536 (przeczytaj,<a href="http://blog.milosierny.net/2009/01/21/egzamin-70-536-application-development-foundation/"> jak przygotować się do egzaminu 70-536</a>). Zdanie dwóch tych dwóch egzaminów skutkuje przyznaniem certyfikatu: Microsoft Certfified Technology Specialist  &#8211; .NET Framework 3.5, ASP.NET Application. Jeśli zdałeś te dwa egzaminy to jesteś wśród 59 osób w Polsce (dane na 8 grudnia 2009 – możesz zajrzeć do oficjalnej <a href="http://www.microsoft.com/poland/certyfikacje/mcp/stat.mspx">statystyki</a>). Brzmi nieźle, prawda? <img src='http://blog.milosierny.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Jeśli chcesz uzyskać wyższy poziom certyfikacji  &#8211; Microsoft Professional Developer (MPD) w dziedzinie ASP.NET na platformie .NET 3.5 i znaleźć się wśród 20 osób w Polsce posiadających ten certyfikat, będziesz zainteresowany zdaniem egzaminu <a href="http://www.microsoft.com/learning/en/us/exam.aspx?ID=70-564">70-564: Pro: Designing and Developing ASP.NET Applications Using the Microsoft .NET Framework 3.5</a>.</p>
<h1>Podsumowanie</h1>
<p>Na koniec krótkie podsumowanie:</p>
<ol>
<li>Egzamin 70-562 jest dla programistów ASP.NE T      z kilkuletnim doświadczeniem.</li>
<li>Istnieje sporo materiałów do nauki do      egzaminu, w tym książka z MS-Press typu Self-Paced.</li>
<li>Przydatne jest wykonywanie opisywanych ćwiczeń (pisanie kodu), tak żeby zaznajomić się z treścią w sposób praktyczny.</li>
<li>Pomocne jest rozwiązywanie przykładowych testów i wyciąganie wniosków ze swoich błędnych odpowiedzi.</li>
<li>Zdanie dwóch egzaminów 70-536 i 70-562      skutkuje uzyskaniem certyfikatu Microsoft Certified Specialist.</li>
</ol>
<p>Powodzenia!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2009/12/16/egzamin-70-562-net-framework-3-5-asp-net-application-development-%e2%80%93-jak-zdac/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Łączenie kontrolek Web Parts w ASP.NET 2.0</title>
		<link>http://blog.milosierny.net/2009/11/30/laczenie-webpartow-w-asp-net-2-0/</link>
		<comments>http://blog.milosierny.net/2009/11/30/laczenie-webpartow-w-asp-net-2-0/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 22:52:21 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Bez kategorii]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[web 2.0]]></category>
		<category><![CDATA[web parts]]></category>

		<guid isPermaLink="false">http://blog.milosierny.net/?p=54</guid>
		<description><![CDATA[W ASP.NET 2.0 wprowadzono interesującą i wydajną funkcjonalność &#8211; Web Parts. Czym są Web Parts? W skrócie: są to pewne zamknięte komponenty aplikacji internetowej, które są tworzone i zarządzane w jednolity sposób. Jedną z najbardziej użytecznych cech web partów (czasami będę odmieniać przez przypadki, ponieważ nie udało mi się znaleźć żadnego dobrego polskiego odpowiednika) jest [...]]]></description>
			<content:encoded><![CDATA[<p>W ASP.NET 2.0 wprowadzono interesującą i wydajną funkcjonalność &#8211; <strong>Web Parts</strong>. Czym są Web Parts? W skrócie: są to pewne zamknięte komponenty aplikacji internetowej, które są tworzone i zarządzane w jednolity sposób. Jedną z najbardziej użytecznych cech web partów (czasami będę odmieniać przez przypadki, ponieważ nie udało mi się znaleźć żadnego dobrego polskiego odpowiednika) jest to, że mogą być one dodawane, usuwane i edytowane nie tylko przez programistów, ale też przez użytkowników Twojej aplikacji internetowej. Web parts w akcji możesz zobaczyć np. na stronie: <a href="http://igoogle.com">igoogle.com</a>.</p>
<p>Ten wpis nie będzie o tworzeniu web partów &#8211; chcę skupić się na pewnym małym wycinku tematu &#8211; mianowicie na tworzeniu połączeń między web partami.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-0055460474580388";
/* 468x60, utworzono 09-11-27 */
google_ad_slot = "0413534588";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<h1>Po co łączyć web parts</h1>
<p>Przypuśćmy, że tworzysz aplikację webową, która wyświetla szczegóły na temat europejskich miast. Chciałbyś zorganizować te stroną w taki sposób, żeby korzystała z web parts. W ten sposób umożliwiłbyś użytkownikowi samodzielne zarządzanie wyglądem strony. Załóżmy, że w jednym web parcie użytkownik będzie wpisywał (bądź wybierał z listy) nazwę miasta. W innych web partach pojawią się wówczas informacje takie jak:</p>
<ul>
<li>liczba ludności miasta,</li>
<li>slideshow ze zdjęciami z miasta,</li>
<li>aktualna prognoza pogody, itd.</li>
</ul>
<p>Aby uzyskać opisaną funkcjonalność, jako programista, musisz ustalić połączenie między web partami. Można to zrobić na dwa sposoby &#8211; 1) ustalić statyczne połączenie lub 2) umożliwić użytkownikom tworzenie dynamicznych powiązań. Omówię pierwszy z nich.</p>
<h1>Statyczne powiązanie web partów</h1>
<p>Statyczne powiązanie polega na wskazaniu jednego web parta jako dostawcy (<strong>provider</strong>) i jednego bądź więcej odbiorców (<strong>consumer</strong>).</p>
<p>Uwaga: dla ułatwienia jako web partów będziemy używać własnych kontrolek (<strong>user controls</strong>).</p>
<p>Stworzenie dostawcy polega na dodaniu do gotowej kontrolki metody, która będzie zwracała pewną wartość. W naszym przykładzie chcemy, aby była to nazwa miasta pochodząca z rozwijalnej listy. Oto, jak mógłby wyglądać przykładowy kod takiej kontrolki:</p>
<pre class="brush: csharp;">
public partial class CityChooser : System.Web.UI.UserControl
{

    string _cityName = CityData.GetData().First().Name;

    [ConnectionProvider(&quot;My web parts connection&quot;, &quot;GetCityName&quot;)]
    public string GetCityName()
    {
        return _cityName;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
            string userCity = DropDownList1.SelectedValue;
            _cityName = CityData.GetData().First(city =&gt; city.Name == userCity).Name;
        }

    }
}
</pre>
<p>Obiekt <span class="myPre">CityData</span> zawiera po prostu listę miast w postaci struktur zawierających wszystkie potrzebne dane (np. pole <span class="myPre">Name</span> czy <span class="myPre">Population</span>). Dokładny wygląd tej klasy nie jest w tej chwili istotny. Najistotniejsza jest metoda:</p>
<pre class="brush: csharp;">
[ConnectionProvider(&quot;My web parts connection&quot;)]
public string GetCityName()
{
    return _cityName;
}
</pre>
<p>Metoda ta (<strong>ważne &#8211; publiczna!</strong>) zwraca po prostu nazwę miasta wybranego z listy rozwijalnej. Atrybut <span class="myPre">ConnectionProvider</span> określa, że jest to nasz dostawca danych dla innych web partów (konsumentów). Tu używamy z jednym parametrem (&#8221;przyjazną&#8221; nazwą połączenia), ale jest też przeciążona wersja z dwoma typu <span class="myPre">string</span>. Wówczas pierwszy określa &#8220;przyjazną&#8221; nazwę naszego połączenia, a drugi definiuje <strong>unikalną</strong> nazwę naszego punktu połączenia. Można pominąć drugi parametr &#8211; wówczas nasz punkt będzie się nazywał <span class="myPre">default</span> (oczywiście, gdybyśmy chcieli zdefiniować drugi <span class="myPre">ConnectionProvider</span>, to wówczas trzeba już użyć drugiego parametru &#8211; nazwa <span class="myPre">default</span> byłaby już zajęta).</p>
<p>Mamy zatem zdefiniowanego dostawcę naszych danych. Czas na konsumentów.</p>
<p>Stworzenie konsumenta polega na dodaniu do kontrolki będącej web partem metody (znów publicznej), która będzie przyjmować parametr &#8211; tego samego typu, jaki jest zwracany przez naszą metodę-dostawcę. Metodą tą należy opatrzyć atrybutem <span class="myPre">ConnectionConsumer</span>. Całość mogłaby wyglądać następująco:</p>
<pre class="brush: csharp;">
public partial class PopulationDisplayer : System.Web.UI.UserControl
{
    [ConnectionConsumer(&quot;My consumer&quot;)]
    public void ShowPopulation(string city)
    {
        lblCityPop.Text = CityData.GetData().First(c =&gt; c.Name == city).Population.ToString();
    }
}
</pre>
<p>I znów najważniejszy jest atrybut <span class="myPre">ConnectionConsumer</span>. Parametry mają takie samo znaczenie jak w poprzednim przypadku.</p>
<p>Teraz, gdy mamy już zdefiniowanego dostawcę i co najmniej jednego odbiorcę, możemy ustalić połączenie. W tym celu musimy stworzyć stronę, na której będą działać nasze web party. Dodajemy oczywiście kontrolkę <span class="myPre">WebPartManager</span> oraz <span class="myPre">WebPartZone</span>, w której w <span class="myPre">ZoneTemplate</span> umieszczamy nasze web party. Kod kontrolki <span class="myPre">WebPartZone</span> może wyglądać następująco:</p>
<pre class="brush: xml;">
&lt;asp:WebPartZone ID=&quot;WebPartZone3&quot; runat=&quot;server&quot; Style=&quot;width: 650px; height: auto;&quot;&gt;
    &lt;ZoneTemplate&gt;
        &lt;uc2:CityChooser ID=&quot;Provider&quot; runat=&quot;server&quot; /&gt;
        &lt;uc3:PopulationDisplayer ID=&quot;Consumer&quot; runat=&quot;server&quot; /&gt;
    &lt;/ZoneTemplate&gt;
&lt;/asp:WebPartZone&gt;
</pre>
<p>Samo powiązanie definiujemy natomiast w kontrolce <span class="myPre">WebPartManager</span> w części <span class="myPre">StaticConnections</span>:</p>
<pre class="brush: xml;">
&lt;asp:WebPartManager ID=&quot;WebPartManager1&quot; runat=&quot;server&quot;&gt;
    &lt;StaticConnections&gt;
        &lt;asp:WebPartConnection
            ID=&quot;CityToPopulation&quot;
            ProviderID=&quot;Provider&quot;
            ConsumerID=&quot;Consumer&quot;&gt;
        &lt;/asp:WebPartConnection&gt;
    &lt;/StaticConnections&gt;
&lt;/asp:WebPartManager&gt;
</pre>
<p>I tak oto, gdy w jednym web parcie z listy wybierzemy miasto, to w drugim zobaczymy liczbę ludności tego miasta:</p>
<div id="attachment_71" class="wp-caption alignnone" style="width: 488px"><img class="size-full wp-image-71" title="Powiązanie Web Parts " src="http://blog.milosierny.net/wp-content/uploads/2009/11/web-parts.PNG" alt="Powiązanie Web Parts " width="478" height="371" /><p class="wp-caption-text">Powiązanie Web Parts </p></div>
<p>Gdybyśmy w atrybutach definiujących naszego dostawcę i konsumenta podali unikalne nazwy dla naszych punktów, np:</p>
<pre class="brush: csharp;">
[ConnectionProvider(&quot;My web parts connection&quot;, &quot;ProvideData&quot;)]
</pre>
<pre class="brush: csharp;">
[ConnectionConsumer(&quot;My consumer&quot;, &quot;ConsumeData&quot;)]
</pre>
<p>wówczas kod kontrolki <span class="myPre">WebPartManager</span> wyglądałby nieco inaczej:</p>
<pre class="brush: csharp;">
    &lt;asp:WebPartManager ID=&quot;WebPartManager1&quot; runat=&quot;server&quot;&gt;
        &lt;StaticConnections&gt;
            &lt;asp:WebPartConnection
            ID=&quot;CityToPopulation&quot;
            ProviderID=&quot;Provider&quot;
            ProviderConnectionPointID=&quot;ProvideData&quot;
            ConsumerID=&quot;Consumer&quot;
            ConsumerConnectionPointID=&quot;ConsumeData&quot;&gt;
            &lt;/asp:WebPartConnection&gt;
        &lt;/StaticConnections&gt;
    &lt;/asp:WebPartManager&gt;
</pre>
<p>Musielibyśmy wówczas określić, że chodzi nam o konkretne metody za pomocą właściwości: <span class="myPre">ProviderConnectionPointID</span> i <span class="myPre">ConsumerConnectionPointID</span>.</p>
<p>Gdybyśmy chcieli użyć większej ilości konsumentów, musielibyśmy zdefiniować odpowiednie <span class="myPre">WebPartConnection</span> dla każdej pary web partów.</p>
<p>W taki sposób można łatwo definiować statyczne połączenia. O tym, jak umożliwić użytkownikom strony tworzenie dynamicznych połączeń, będzie następny (krótki) wpis.</p>
<p>Tym razem załączam kod źródłowy przykładowego rozwiązania &#8211; wersja dla Visual Studio 2008. Żeby korzystać z web partów, trzeba mieć SQL Server wersję Express, ponieważ web parts korzystają z bazy danych (<span class="myPre">App_Data/ASPNETDB.MDF</span>), żeby zapamiętywać preferencje użytkownika. Paczka z kodem nie zawiera tego pliku &#8211; trzeba go sobie stworzyć samemu (np. przy pomocy narzędzia ASP.NET Configuration).</p>
<p><span class="myPre"><img class="alignnone size-full wp-image-74" style="vertical-align: middle; margin-right: 10px;" title="vssolution" src="http://blog.milosierny.net/wp-content/uploads/2009/11/vssolution.gif" alt="vssolution" width="30" height="28" /><a href="http://blog.milosierny.net/wp-content/uploads/2009/11/WebParts-static-connections-blog.milosierny.zip">WebParts static connections &#8211; kod C#</a> (6,29 KB)</span></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2009/11/30/laczenie-webpartow-w-asp-net-2-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Zdjęcia i film z wizyty Steve&#039;a Ballmera w Polsce</title>
		<link>http://blog.milosierny.net/2009/05/05/zdjecia-i-film-z-wizyty-stevea-ballmera-w-polsce/</link>
		<comments>http://blog.milosierny.net/2009/05/05/zdjecia-i-film-z-wizyty-stevea-ballmera-w-polsce/#comments</comments>
		<pubDate>Tue, 05 May 2009 15:19:24 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ballmer]]></category>
		<category><![CDATA[film]]></category>
		<category><![CDATA[photosynth]]></category>
		<category><![CDATA[steve]]></category>
		<category><![CDATA[zdjęcia]]></category>

		<guid isPermaLink="false">http://bartoszmilosierny.wordpress.com/?p=41</guid>
		<description><![CDATA[W Internecie pojawił się film ze spotkania Steve&#8217;a Ballmera z polskimi społecznościami IT.
Polecam także stronę ze zdjęciami ze spotkania. Fotografie są wyświetlane za pomocą rewelacyjnego programu &#8211; Photosynth &#8211; opracowanego w Microsoft Live Labs.
]]></description>
			<content:encoded><![CDATA[<p>W Internecie pojawił się <a href="http://mschnlnine.vo.llnwd.net/d1/edge/4/7/8/2/SteveBallmerPLCommunity_2MB_edge.wmv">film</a> ze spotkania Steve&#8217;a Ballmera z polskimi społecznościami IT.</p>
<p>Polecam także <a href="http://photosynth.net/view.aspx?cid=66aa39fc-a537-4d82-be0e-a58c01ed6ea4">stronę</a> ze zdjęciami ze spotkania. Fotografie są wyświetlane za pomocą rewelacyjnego programu &#8211; <a href="http://photosynth.net/">Photosynth</a> &#8211; opracowanego w Microsoft Live Labs.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2009/05/05/zdjecia-i-film-z-wizyty-stevea-ballmera-w-polsce/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://mschnlnine.vo.llnwd.net/d1/edge/4/7/8/2/SteveBallmerPLCommunity_2MB_edge.wmv" length="260561586" type="video/x-ms-wmv" />
		</item>
		<item>
		<title>Implementacja drzewa trie w C#</title>
		<link>http://blog.milosierny.net/2009/04/27/implementacja-drzewa-trie-w-csharp/</link>
		<comments>http://blog.milosierny.net/2009/04/27/implementacja-drzewa-trie-w-csharp/#comments</comments>
		<pubDate>Mon, 27 Apr 2009 17:27:09 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[algorytmy]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[trie]]></category>

		<guid isPermaLink="false">http://bartoszmilosierny.wordpress.com/?p=21</guid>
		<description><![CDATA[Ostatnio przy implementacji aplikacji dla platformy Mediaroom, napotkałem na problem ustalania podzbioru pewnego danego zbioru napisów, który to podzbiór miałby zawierać wszystkie stringi rozpoczynające się ustalonym prefiksem. Jak nietrudno się domyśleć, procedura potrzebna mi była do implementacji listy podpowiedzi &#8211; użytkownik rozpoczyna wprowadzanie tekstu, a na ekranie pojawia mu się lista podpowiedzi &#8211; scenariusz szeroko [...]]]></description>
			<content:encoded><![CDATA[<p>Ostatnio przy implementacji aplikacji dla platformy <a href="http://www.microsoft.com/Mediaroom/">Mediaroom</a>, napotkałem na problem ustalania podzbioru pewnego danego zbioru napisów, który to podzbiór miałby zawierać wszystkie stringi rozpoczynające się ustalonym prefiksem. Jak nietrudno się domyśleć, procedura potrzebna mi była do implementacji listy podpowiedzi &#8211; użytkownik rozpoczyna wprowadzanie tekstu, a na ekranie pojawia mu się lista podpowiedzi &#8211; scenariusz szeroko stosowany we współczesnym webie. W aplikacjach dla telewizji ma on jednak o wiele większe znaczenie, bo możliwości wprowadzania tekstu za pomocą pilota są raczej ograniczone (stosuje się metodę triple-tap znaną z komórek).</p>
<p>Problem przedstawia się zatem następująco: mając zadaną tablicę ze stringami (lista wszystkich możliwych sugestii), dla określonego prefiksu (ciągu znaków), podać listę tych stringów z tablicy wejściowej, które rozpoczynają się od prefiksu.</p>
<p>Trywialne rozwiązanie:</p>
<pre class="brush: csharp;">
//dane wejściowe
String[] input = strings.ToArray();

//prefiks, dla którego szukamy podzbioru
String prefix = &quot;ab&quot;;

String[] subset = Array.FindAll&lt;String&gt;(
    input,
    new Predicate&lt;string&gt;(s =&gt; s.StartsWith(prefix))
    );
</pre>
<p>ma jedną zaletę &#8211; zajmuje mało kodu. Niestety poza tym ma same wady:</p>
<ol>
<li>Czas ustalenia interesującego nas podzbioru zależy liniowo od wielkości danych wejściowych (liczby stringów w tablicy). Przy, powiedzmy, 50 tysiącach stringów użytkownik zauważalnie długo czeka na podpowiedź.</li>
<li>Łatwo zauważyć, że dla każdej kolejnej wpisanej litery prefiksu, zawężamy wynik poszukiwań &#8211; dla <em>n-tej</em> litery prefiksu wynikiem jest podzbiór uzyskany w poprzednim kroku, dla <em>n-1</em> litery. Trywialna metoda nie korzysta jednak z tej obserwacji i dla każdej litery proces poszukiwania zaczynany jest na nowo.</li>
</ol>
<p>Z pomocą przychodzą drzewa trie (czyt. <em>traj</em>). Trie jest drzewem poszukiwań, którego wierzchołki są oznaczone kolejnymi prefiksami słów z listy. Prócz prefiksu wierzchołek zawiera informacje o słowach z listy, które &#8220;pasują&#8221; do tego prefiksu. Oczywiście w celach optymalizacji, w drzewie nie są przechowywane same podzbiory wyjściowego zbioru, tylko indeks początkowy i końcowy danego podzbioru.</p>
<p>Przykład:</p>
<div id="attachment_27" class="wp-caption alignnone" style="width: 446px"><a href="http://bartoszmilosierny.wordpress.com/files/2009/04/trie.png"><img class="size-full wp-image-27 " title="Trie - przykład" src="http://bartoszmilosierny.wordpress.com/files/2009/04/trie.png" alt="Trie - przykład" width="436" height="374" /></a><p class="wp-caption-text">Trie - przykład</p></div>
<p>Powyższe drzewo trie zawiera dane o prefiksach dla następującej listy słów:</p>
<ul>
<li>AR</li>
<li>AS</li>
<li>B</li>
<li>DO</li>
<li>ELA</li>
<li>ELF</li>
<li>EM</li>
</ul>
<p>Żeby otrzymać informację o podzbiorze stringów zaczynających się od prefiksu &#8220;EL&#8221; należy przejść od korzenia przez węzeł &#8220;E&#8221; aż do węzła &#8220;L&#8221;  &#8211; otrzymujemy indeksy 4-5, czyli słowa &#8220;ELA&#8221; i &#8220;ELF&#8221;. Warto zauważyć, że koszt wyszukania interesującego nas podzbioru nie zależy teraz od wielkości danych wejściowych.</p>
<p>Zanim przystąpimy do napisania funkcji budującej drzewo, zdefiniujmy najpierw dane pomocnicze: strukturę <code>Prefix</code>, i klasę <code>TreeNode&lt;T&gt;</code>.</p>
<p>Prefix:</p>
<pre class="brush: csharp;">
public struct Prefix
{
    int _start;
    public int Start
    {
        get { return _start; }
        set { _start = value; }
    }

    int _end;
    public int End
    {
        get { return _end; }
        set { _end = value; }
    }

    char _letter;
    public char Letter
    {
        get { return _letter; }
        set { _letter = value; }
    }

    public Prefix(int start, int end, char letter)
    {
        _start = start;
        _end = end;
        _letter = letter;
    }
}
</pre>
<p>TreeNode:</p>
<pre class="brush: csharp;">
public class TreeNode&lt;T&gt;
{
    private TreeNode _parent = null;
    protected List&lt;TreeNode&gt; _children = new List&lt;TreeNode&gt;();
    private T _value;

    public void AddChild(TreeNode child)
    {
        if (!_children.Contains(child))
        {
            _children.Add(child);
            child._parent = this;
        }
    }

    public TreeNode Parent
    {
        get { return _parent; }
        set { _parent = value; }
    }

    public TreeNode(T value)
    {
        this._value = value;
    }

    public TreeNode(T value, TreeNode[] children)
    {
        new TreeNode(value);
        _children = new List&lt;TreeNode&gt;(children);
    }

    public T Value
    {
        get { return _value; }
        set { _value = value; }
    }

    public List&lt;TreeNode&gt; Children
    {
        get { return _children; }
    }
}
</pre>
<p>Powyższa klasa jest bardzo prostą implementacją węzła drzewa przechowującego zadany typ danych o zbiorze synów trzymanych za pomocą listy generycznej.</p>
<p>Mając tak zdefiniowane klasy pomocnicze, możemy napisać rekurencyjną metodę tworzącą drzewo trie:</p>
<pre class="brush: csharp;">
public class Trie
{
    private String[] _input;
    private TreeNode&lt;Prefix&gt; _tree;
    private char[] _availableChars;

    private void MakeNode(TreeNode&lt;Prefix&gt; root, int indexOfString)
    {
        int wordIndex = root.Value.Start;
        int lastIndex = wordIndex;
        bool nodeStarted = false;
        char character = '';
        char prevChar = character;
        while (wordIndex &lt;= root.Value.End)
        {
            String s = _input[wordIndex];
            prevChar = character;
            if (indexOfString &lt; s.Length)
            {
                if (s[indexOfString] != character)
                {
                    character = s[indexOfString];
                    if (nodeStarted)
                    {
                        Prefix newPair = new Prefix(lastIndex, wordIndex - 1, prevChar);
                        lastIndex = wordIndex;
                        TreeNode&lt;Prefix&gt; newNode = new TreeNode&lt;Prefix&gt;(newPair);
                        root.AddChild(newNode);
                        nodeStarted = false;
                    }
                }
                else
                {
                    nodeStarted = true;
                    wordIndex++;
                }
            }
            else
            {
                wordIndex++;
            }
        }
        if (nodeStarted)
        {
            root.AddChild(new TreeNode&lt;Prefix&gt;(new Prefix(lastIndex, root.Value.End, character)));
        }
        foreach (TreeNode&lt;Prefix&gt; child in root.Children)
        {
            MakeNode(child, indexOfString + 1);
        }
    }

    public Trie(String[] input)
    {
        _input = input;
        _tree = new TreeNode&lt;Prefix&gt;(new Prefix(0, _input.Length - 1, ''));
        MakeNode(_tree, 0);
    }
}
</pre>
<p>Kluczowa jest metoda MakeNode, która w sposób rekurencyjny tworzy listę synów dla istniejących wierzchołków drzewa trie, w oparciu o drugi parametr, który określa indeks bieżącej litery w szukanych stringach.</p>
<p>Mając utworzone drzewo trie dla danego zbioru stringów, możemy wywoływać następującą metodę z klasy <code>Trie</code>:</p>
<pre class="brush: csharp;">
        public String[] GetStringsForPrefix(string prefix)
        {
            TreeNode&lt;Prefix&gt; current = _tree;
            for (int i = 0; i &lt; prefix.Length; i++)
            {
                current = current.Children.Find(new Predicate&lt;TreeNode&lt;Prefix&gt;&gt;(t =&gt; t.Value.Letter == prefix[i]));
                if (current == null)
                {
                    return null;
                }
            }
            int length = current.Value.End - current.Value.Start + 1;
            string[] result = new string[length];
            Array.Copy(_input, current.Value.Start, result, 0, length);
            return result;
        }
</pre>
<p>która zwróci nam interesujący nas podzbiór stringów. W ten sposób mamy rozwiązanie początkowego problemu.</p>
<p>Powyższa implementacja struktury danych trie z całą pewnością może być bardziej optymalna &#8211; chciałem jednak zachować czytelność kodu i zaprezentować ogólną ideę tworzenia drzewa trie, a nie skupiać się na optymalizacji.</p>
<p>Wadą drzew trie jest ich stosunkowo duży rozmiar w pamięci (jak duży? od czego zależy? czy można go zmniejszyć?). Można to poprawić stosując tzw. <a href="http://pl.wikipedia.org/wiki/Drzewo_Patricia">drzewa Patricia</a>, czyli wariant drzew trie, w których zamiast liter do etykietowania krawędzi (w naszej implementacji: węzłów), stosujemy całe stringi. Takie skompresowane drzewo trie tworzy się przez usuwanie węzłów mających tylko jednego syna i modyfikację drzewa, tak aby skrócić ścieżkę poszukiwań.</p>
<p>Drzewa trie nie są jedynym sposobem na szybkie rozwiązanie opisanego na wstępie problemu, ale warto wiedzieć o ich istnieniu i umieć je zaimplementować. W szczególności dlatego, że w pewnych <a href="http://en.wikipedia.org/wiki/Trie#Advantages_and_drawbacks.2C_relative_to_binary_search_tree">okolicznościach </a>są wydajniejsze niż drzewa <a href="http://pl.wikipedia.org/wiki/Binarne_drzewo_poszukiwa%C5%84">BST</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2009/04/27/implementacja-drzewa-trie-w-csharp/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Steve Ballmer &#8211; spotkanie ze społecznościami IT w Polsce</title>
		<link>http://blog.milosierny.net/2009/04/24/steve-ballmer-spotkanie-ze-spolecznosciami-it-w-polsce/</link>
		<comments>http://blog.milosierny.net/2009/04/24/steve-ballmer-spotkanie-ze-spolecznosciami-it-w-polsce/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 15:39:01 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://bartoszmilosierny.wordpress.com/?p=16</guid>
		<description><![CDATA[W czwartek 23 kwietnia w hotelu Sheraton w Warszawie odbyło się spotkanie Steve&#8217;a Ballmera, CEO Microsoftu z członkami polskich społeczności IT. Byłem tam i z przyjemnością opiszę, jak wyglądało to spotkanie.
Steve przybył prawie punktualnie &#8211; nie licząc kwadransa akademickiego. Kiedy wchodził na salę miał na sobie czerwono-biały szalik z napisem &#8220;Polska&#8221;, który dostał od kogoś [...]]]></description>
			<content:encoded><![CDATA[<p>W czwartek 23 kwietnia w hotelu Sheraton w Warszawie odbyło się spotkanie Steve&#8217;a Ballmera, CEO Microsoftu z członkami polskich społeczności IT. Byłem tam i z przyjemnością opiszę, jak wyglądało to spotkanie.</p>
<p>Steve przybył prawie punktualnie &#8211; nie licząc kwadransa akademickiego. Kiedy wchodził na salę miał na sobie czerwono-biały szalik z napisem &#8220;Polska&#8221;, który dostał od kogoś w Polsce i obiecał powiesić sobie w gabinecie.</p>
<p>Spotkanie zaczęło się od 15-minutowego przemówienia. Właściwie ta prelekcja bardziej przypominała show &#8211; Steve poruszał się na scenie oświetlony reflektorami &#8211; nie miał żadnych notatek ani pulpitu, nie prezentował żadnych slajdów.</p>
<p>W swoim wystąpieniu Steve poruszył kwestię kryzysu ekonomicznego i jego wpływu na techonologię. Zdaniem prezesa Microsoftu, właśnie teraz &#8211; podczas kryzysu &#8211; jest czas na inwestowanie w nowe rozwiązania i nowe technologie, które zaprocentują, gdy sytuacja gospodarcza poprawi się.</p>
<p>Ballmer powiedział także, że Microsoft  jest zdecydowany wydać w najbliższym czasie ok. <strong>9 miliardów dolarów na badania i rozwój. Oznacza to 45000 etatów.</strong></p>
<p>W jakich obszarach technologia będzie się rozwijać najbardziej prężnie? Wg CEO Microsoftu głównie w zakresie poprawiania interakcji między użytkownikiem a komputerem: <strong>zaawansowane rozpoznawanie mowy czy gestów.</strong> Steve wyraził także niezadowolenie ze sposobu w jaki, w dzisiejszych czasach działają wyszukiwarki (tu pozwolił sobie na drobne żarty z konkurencyjnego Google). Przytaczał statystyki, z których wynika, że około połowa poszukiwań konkretnych treści kończy się fiaskiem oraz że przeciętne <strong>zapytanie składa się z 2,2 słowa</strong>. Powiedział także:</p>
<blockquote><p>Im więcej informacji dajesz wyszukiwarce, tym mniej zadowalających wyników otrzymujesz. Silnik nie radzi sobie z dużymi liczbami słów w zapytaniu. Gdy rozmawiasz z prawdziwym człowiekiem, jest zupełnie odwrotnie &#8211; im więcej informacji dostarczysz, tym lepszą odpowiedź dostaniesz.</p></blockquote>
<p>Po tym krótkim wystąpieniu nadszedł czas na sesję pytań i odpowiedzi. Pytania dotyczyły najróżniejszych tematów, ale postaram się przytoczyć te najciekawsze:</p>
<blockquote><p>Gdybyś miał opisać firmę Microsoft za pomocą jednego słowa, jakiego słowa byś użył?</p></blockquote>
<p>Steve chwilę zastanawiał się, pytając z niedowierzaniem &#8220;one word? one word???&#8221;, kiedy nagle ktoś z sali krzyknął &#8220;awesome!&#8221;. Steve podchwycił i powiedział, że gdyby miał do dyspozycji dwa słowa powiedziałby:</p>
<blockquote><p>Awesome, baby!</p></blockquote>
<p>Poważna odpowiedź na pytanie brzmiała natomiast:</p>
<blockquote><p>Popular innovation</p></blockquote>
<p>Steve wyjaśnił, że Microsoft jest firmą, która dba o innowacje i wdraża nowe rozwiązania, ale jej celem jest poruszenie masowego odbiorcy &#8211; wpłynięcie na jak największą liczbę ludzi. Jako kontrprzykład podał firmę Apple &#8211; która wg niego jest innowacyjna, ale nie trafia do mas.</p>
<p>Inne pytanie, dotyczyło patentów. Steve wyraził pogląd, że patenty &#8211; jeśli reprezentują prawdziwą wartość &#8211; mają sens i popiera je. Skrytykował natomiast rozwiązania prawne zarówno w Stanach jak i w Unii, ponieważ według niego pozwalają na zgłaszanie bezsensownych patentów, za którymi nie kryje się żadna wartość.</p>
<p>Zapytany czy statystyki pokazujące, że większość specjalistów IT nie zmigruje do Windows 7 w pierwszym roku po jego wydaniu spowodują opóźnienie wydania nowego systemu, Steve powiedział, że jest to wręcz powód, dla którego Microsoft powinien przyspieszyć datę wydania siódemki. Wyraził także przekonanie, że ci sami specjaliści, którzy podejmą decyzję o pozostaniu przy XP czy Viście w firmach, w swoich domach na pewno bardzo szybko zainstalują nowy Windows.</p>
<p>Spotkanie szybko dobiegło końca, ale pozostawiło bardzo przyjemne wrażenie. Chyba głównie z powodu bezpośredniego, bezpretensjonalnego i bardzo energicznego stylu bycia Steve&#8217;a. Podczas całego spotkania utrzymywał żywy kontakt z publicznością, często żartował, swobodnie poruszał się po całej scenie, gestykulował. Bardzo dobrze się go słuchało.</p>
<p>Jedyną wadą spotkania było to, że trwało tylko jakieś 40 minut. No i Steve tym razem nie wykonał popisowego monkey dance&#8230; <img src='http://blog.milosierny.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2009/04/24/steve-ballmer-spotkanie-ze-spolecznosciami-it-w-polsce/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>3. Spotkanie Bydgoskiej Grupy Developerów .NET</title>
		<link>http://blog.milosierny.net/2009/01/28/3-spotkanie-bydgoskiej-grupy-developerow-net/</link>
		<comments>http://blog.milosierny.net/2009/01/28/3-spotkanie-bydgoskiej-grupy-developerow-net/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 23:25:53 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://bartoszmilosierny.wordpress.com/?p=14</guid>
		<description><![CDATA[Jeżeli mieszkasz w Bydgoszczy, to być może będziesz szczególnie zainteresowany poniższą informacją.
Od kilku miesięcy w Bydgoszczy działa lokalna grupa offline wspierana przez Microsoft - Bydgoska Grupa Developerów .NET. Jaki jest cel istnienia grupy?
W Internecie istnieje mnóstwo online&#8217;owych społeczności związanych z programowaniem w .NET &#8211; można choćby wymienić prężnie działający portal codeguru.pl. Nie wszystkie jednak wydarzenia [...]]]></description>
			<content:encoded><![CDATA[<p>Jeżeli mieszkasz w Bydgoszczy, to być może będziesz szczególnie zainteresowany poniższą informacją.</p>
<p>Od kilku miesięcy w Bydgoszczy działa lokalna grupa offline wspierana przez <a href="http://ms-groups.pl/communities/Strony/default.aspx">Microsoft </a>- <a href="http://ms-groups.pl/bgd.net">Bydgoska Grupa Developerów .NET</a>. Jaki jest cel istnienia grupy?</p>
<p>W Internecie istnieje mnóstwo online&#8217;owych społeczności związanych z programowaniem w .NET &#8211; można choćby wymienić prężnie działający portal <a href="http://www.codeguru.pl">codeguru.pl</a>. Nie wszystkie jednak wydarzenia mogą mieć miejsce w przestrzeni wirtualnej &#8211; na forach, blogach czy portalach. Programiści, którzy lubią swoją pracę mają potrzebę wymiany poglądów, uczenia się czegoś nowego, a chyba nie ma ku temu lepszej okazji niż spotkanie w realu. Dlatego właśnie w całej Polsce tworzone są lokalne grupy offline (w tej chwili jest ich ponad 20 i ciągle powstają następne).</p>
<p>BGD.NET organizuje spotkania (mniej więcej raz w miesiącu), na których prelegenci &#8211; profesjonalni programiści i specjaliści IT &#8211; prezentują wybrane zagadnienia związane z platformą .NET, programowaniem, bazami danych czy nowinkami w świecie programowania. Liczymy na to, że na spotkaniach po prezentacji wywiążą się ciekawe, owocne dyskusje.</p>
<p>Poza tym spotkania grup stanowią świetną okazję do poznania ludzi z innych firm w mieście, do zorientowania się czym zajmują się inni programiści czy jakie ciekawe projekty są rozwijane w regionie.</p>
<p>Zwykle grupy offline dysponują darmowymi pomocami technicznymi w formie elektronicznych prezentacji, podręczników czy przykładowych projektów. Dostępne są też książki (najczęściej wydane przez Microsoft Press), które można wypożyczyć.</p>
<p>Warto też dodać, że grupy zostały ostatnio objęte <a href="http://www.ms-groups.pl/bgd.net/Lists/News/DispForm.aspx?ID=1">patronatem czasopisma NEXT</a>.</p>
<p>Najbliższe spotkanie grupy bydgoskiej już 18 lutego. Prezentację poprowadzą Paweł Gliwiński i Marek Graczykowski &#8211; programiści zajmujący się IPTV. Tematyka będzie dotyczyć wzorców projektowych w języku C#. Może się wydawać, że o wzorcach projektowych powiedziano już wszystko, a jednak dla niektórych programistów ich właściwe używanie stanowi niemałą zagadkę. Prelegenci postarają się ją rozwiązać i zaprezentują praktyczne zastosowanie niektórych wzorców z przykładowymi scenariuszami użycia.</p>
<p>Zachęcam do <a href="http://ms-groups.pl/_layouts/MSG/Registration/Register.aspx">założenia konta</a> w portalu ms-groups.pl, a potem do <a href="http://ms-groups.pl/bgd.net/Lists/Rejestracja%20na%203%20spotkanie/NewForm.aspx?RootFolder=/bgd.net/Lists/Rejestracja%20na%203%20spotkanie&amp;Source=http://ms-groups.pl/bgd.net/Lists/Rejestracja%2520na%25203%2520spotkanie/AllItems.aspx">rejestracji</a> na 3. spotkanie BGD.NET.</p>
<p>A co jeśli bezkresne szczęście wynikające z mieszkania w Bydgoszczy nie jest Twoim udziałem? :&gt; Sprawdź, czy w Twoim mieście działa grupa offline &#8211; portal <a href="http://ms-groups.pl/communities/Strony/default.aspx">ms-groups.pl</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2009/01/28/3-spotkanie-bydgoskiej-grupy-developerow-net/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Egzamin 70-536: Application Development Foundation</title>
		<link>http://blog.milosierny.net/2009/01/21/egzamin-70-536-application-development-foundation/</link>
		<comments>http://blog.milosierny.net/2009/01/21/egzamin-70-536-application-development-foundation/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 11:25:19 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[egzamin]]></category>
		<category><![CDATA[mcp]]></category>
		<category><![CDATA[mcts]]></category>
		<category><![CDATA[microsoft]]></category>

		<guid isPermaLink="false">http://bartoszmilosierny.wordpress.com/?p=7</guid>
		<description><![CDATA[Większość programistów po zdobyciu pewnego doświadczenia odczuwa potrzebę oficjalnego poświadczenia swoich umiejętności. Taką możliwość dają certyfikaty – są honorowane na całym świecie i obiektywnie potwierdzają zdobytą wiedzę i praktyczne umiejętności.
Ponieważ na co dzień zajmuję się technologiami „okołodotnetowymi” – głównie pisaniem aplikacji webowych przy użyciu frameworka 2.0, postanowiłem podejść do egzaminu Microsoftu o łatwo zapamiętywalnym tytule [...]]]></description>
			<content:encoded><![CDATA[<p>Większość programistów po zdobyciu pewnego doświadczenia odczuwa potrzebę oficjalnego poświadczenia swoich umiejętności. Taką możliwość dają certyfikaty – są honorowane na całym świecie i obiektywnie potwierdzają zdobytą wiedzę i praktyczne umiejętności.</p>
<p>Ponieważ na co dzień zajmuję się technologiami „okołodotnetowymi” – głównie pisaniem aplikacji webowych przy użyciu frameworka 2.0, postanowiłem podejść do egzaminu Microsoftu o łatwo zapamiętywalnym tytule <a href="http://www.microsoft.com/learning/en/us/exams/70-536.aspx">70-536 – TS: Microsoft .NET Framework – Application Development Foundation</a>.</p>
<p><script type="text/javascript"><!--
google_ad_client = "pub-0055460474580388";
/* 468x60, utworzono 09-11-27 */
google_ad_slot = "0413534588";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></p>
<p>Tytuł egzaminu świetnie oddaje szeroki zakres obejmowany zagadnień. 70-536 sprawdza praktyczną i teoretyczną wiedzę dotycząca .NET 2.0. Obejmuje wszystkie dziedziny programowania poczynając od typów danych, operacje I/0 przez szyfrowanie danych i bezpieczeństwo kodu aż po globalizację i biblioteki do rysowania. Tematyka jest zatem rozległa, ale jednocześnie dość spójna.</p>
<p>Podczas przygotowywania się do egzaminu korzystałem głównie z książki z rodzaju self-paced (<a href="http://www.microsoft.com/learning/en/us/books/9469.aspx">MCTS Self-Paced Training Kit (Exam 70-536): Microsoft® .NET Framework 2.0 Foundation</a>). Rozdział po rozdziale omawia ona większość zagadnień dotyczących frameworka. Materiał jest dobrze podzielony pod względem logicznym, każdy rozdział zawiera kilka lekcji, które z kolei kończą się podsumowaniem i kilkoma pytaniami testowymi. Informacje jednak są podane w sposób niemal encyklopedyczny – nie jest to książka, w której autor „zaprzyjaźnia się” z czytelnikiem (natknąłem się jednak na jeden żarcik w rozdziale o serializacji: „<em>Teleportation in science-fiction is a good example of serialization (though teleportation is not currently supported in .NET Framework)</em>”. <img src='http://blog.milosierny.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Pomimo sporej objętości książka nie jest pełnym przewodnikiem po programowaniu w .NET, dlatego podczas przygotowań korzystałem także z biblioteki <a href="http://msdn.microsoft.com/">MSDN</a>.</p>
<p>Poza tym książka niestety zawiera sporo błędów – przeglądając <a href="http://support.microsoft.com/kb/923018">erratę</a> trudno oprzeć się wrażeniu, że aż roi się od błędów. W rzeczywistości nie jest tak źle, a większość błędów można bez trudu wykryć samemu. Jest to jednak odrobinę drażniące.</p>
<p>Podczas przygotowań starałem się pisać testowe aplikacje opisane w labach po każdej lekcji. Myślę, że taki sposób interaktywnej nauki jest najefektywniejszy. W ten sposób szybciej zapamiętuje się kolejność wykonywania kroków dla pewnych specyficznych zadań (np. szyfrowanie pliku kluczem asymetrycznym czy wywołanie zapytania przez Windows API) oraz nazwy i sygnatury metod i konstruktorów</p>
<p>Do Training Kita dołączona jest płytka z przykładowymi testowymi pytaniami (w sumie ponad 300 pytań ze wszystkich kategorii). Na kilka dni przed egzaminem skupiłem się prawie wyłącznie na rozwiązywaniu zestawu testów. Przyzwyczaja to do formy pytań i uczy szukania odpowiedzi w jak najprostszy sposób (np. szybkie porównywanie odpowiedzi w celu wyeliminowania oczywistych błędnych). Z drugiej jednak strony po pewnym czasie większość pytań znałem na pamięć i w zasadzie nie czytałem ich treści. Jak można się domyśleć, nie miałem problemów, żeby zaliczyć każdy zestaw testowy.</p>
<p>Czas przygotowań upłynął szybko (słynne wrażenie<em> jednego brakującego dnia)</em> i nadszedł dzień egzaminu. Zdawałem w ośrodku szkoleniowym <a href="http://www.softronic.pl/">Softronic</a> w Poznaniu. Miejsce niczym niewyróżniające się, nie zaskoczyło ani pozytywnie ani negatywnie. Chwilowym problemem była grupa młodych kobiet (złośliwi twierdzą, że grupy młodych kobiet zawsze stanowią problem dla programistów). Dziewczyny miały przerwę w szkoleniu i dość głośno wymieniały uwagi. Ten konkretny problem został rozwiązany, ale uważam, że w centrum szkoleniowym sale egzaminacyjne powinny być lepiej odseparowane od deskupiających dźwięków z zewnątrz.</p>
<p>Niestety, nie mogę napisać zbyt wiele na temat samego egzaminu, ponieważ każdy przystępujący podpisuję umowę <strong>NDA (Non-Disclosure Agreement)</strong>. Mogę jedynie stwierdzić, że egzamin był trochę trudniejszy niż się spodziewałem, ale te godziny spędzone na przygotowaniach robią swoje i nawet jeśli nie byłem w stu procentach pewien odpowiedzi, to wyrobiona intuicja podpowiadała najbardziej prawdopodobne rozwiązania.<br />
Intuicja mnie nie zawiodła – udało mi się zdać egzamin na <strong>858 </strong>punktów (zaliczenie od 700) i uzyskałem tytuł <a href="http://www.microsoft.com/poland/certyfikacje/mcp/mcp/sixsteps.mspx">MCP</a> (Microsoft Certified Professional)!</p>
<p>Następnym krokiem będzie zdanie egzaminu 70-528: Web-based Client Development i, jeśli dobrze pójdzie, uzyskam tytuł <a href="http://www.microsoft.com/poland/certyfikacje/mcp/mcts/default.mspx">MCTS</a> (Microsoft Certified Technology Specialist).</p>
<p>Jeśli miałbym podsumować ten egzamin, to wydaje mi się, że najtrudniej jest postanowić, że się przystępuje do egzaminu. Bo kiedy ustali już się termin, to nie innego wyjścia – trzeba się nauczyć i zdać. Wszystkim przystępującym do egzaminu życzę powodzenia!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2009/01/21/egzamin-70-536-application-development-foundation/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Hello world!</title>
		<link>http://blog.milosierny.net/2009/01/20/hello-world/</link>
		<comments>http://blog.milosierny.net/2009/01/20/hello-world/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 13:39:19 +0000</pubDate>
		<dc:creator>Bartosz</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[start]]></category>

		<guid isPermaLink="false">http://blog.milosierny.net/?p=4</guid>
		<description><![CDATA[Test
Halo, halo czy to działa?
Start.
]]></description>
			<content:encoded><![CDATA[<h1>Test</h1>
<p>Halo, halo czy to działa?<br />
Start.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.milosierny.net/2009/01/20/hello-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
