<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://zine.net.pl/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>. jak .NET by Maciej Aniserowicz</title><link>http://zine.net.pl/blogs/procent/default.aspx</link><description>NET &amp; stuff blog by Procent</description><dc:language /><generator>CommunityServer 2.1 SP2 (Build: 61129.2)</generator><item><title>Wyrażenia lambda w praktyce - MethodWrappers</title><link>http://zine.net.pl/blogs/procent/archive/2008/11/12/wyra-enia-lambda-w-praktyce-methodwrappers.aspx</link><pubDate>Wed, 12 Nov 2008 17:35:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:2379</guid><dc:creator>Procent</dc:creator><slash:comments>2</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/2379.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=2379</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=2379</wfw:comment><description>&lt;p&gt;Kiedyś już wspominałem o fajnym wykorzystaniu wyrażeń lambda w poście &lt;a href="http://www.maciejaniserowicz.com/post/2008/03/15/Wyrazenia-lambda-i-extension-methods-aspektejszyn.aspx" target="_blank"&gt;Wyrażenia lambda i extension methods - aspektejszyn&lt;/a&gt;. Dzisiaj przytoczę kolejne przykłady takiego ich zastosowania, które potrafią znacząco ograniczyć ilość powtarzalnego kodu w kodzie (badaniem ilości cukru w cukrze zajął się &lt;a href="http://www.filmweb.pl/f1169/Poszukiwany%2C+poszukiwana,1972" target="_blank"&gt;kto inny&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Całość wrzuciłem sobie do statycznej klasy MethodWrappers, przyjrzyjmy się jej zawartości...&lt;/p&gt;
&lt;h2&gt;IgnoreExceptions()&lt;/h2&gt;
&lt;p&gt;Celem tej metody jest maksymalne skrócenie takiego potwora:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;try&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	CanThrow();
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  &lt;span class="csKeyword"&gt;catch&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  &lt;span class="csKeyword"&gt;try&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 10:&lt;/span&gt;  	WillPossiblyThrowException();
&lt;span class="csLineNumber"&gt; 11:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt; 12:&lt;/span&gt;  &lt;span class="csKeyword"&gt;catch&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 13:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 14:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 15:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt; 16:&lt;/span&gt;  &lt;span class="csKeyword"&gt;try&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 17:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 18:&lt;/span&gt;  	ShouldNotThrowButWhoKnows();
&lt;span class="csLineNumber"&gt; 19:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt; 20:&lt;/span&gt;  &lt;span class="csKeyword"&gt;catch&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 21:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 22:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 23:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Chcemy, aby wykonały się WSZYSTKIE metody, niezależnie od wyrzucanych wyjątków, które zignorujemy. Tak, wiem, łykanie wszystkiego w try/catch jest praktyką NIEPOLECANĄ, jednak skądś takie brzydale znamy, prawda?&lt;/p&gt;
&lt;p&gt;Pierwszy upraszczacz skraca kod do:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  MethodWrappers.IgnoreExceptions(
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  	CanThrow,
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	WillPossiblyThrowException,
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	ShouldNotThrowButWhoKnows
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  	);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Prawda że ładniej? Oto kod podspodowy:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// Executes given operations catching all exceptions.&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// Exceptions thrown by the operations are ignored and do not bubble up to the caller.&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// Exceptions do not prevent other operations from being executed.&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  &lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;static&lt;/span&gt; &lt;span class="csKeyword"&gt;void&lt;/span&gt; IgnoreExceptions(&lt;span class="csKeyword"&gt;params&lt;/span&gt; Action[] operations)
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;foreach&lt;/span&gt; (&lt;span class="csKeyword"&gt;var&lt;/span&gt; operation &lt;span class="csKeyword"&gt;in&lt;/span&gt; operations)
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt; 10:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;try&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 11:&lt;/span&gt;  		{
&lt;span class="csLineNumber"&gt; 12:&lt;/span&gt;  			operation();
&lt;span class="csLineNumber"&gt; 13:&lt;/span&gt;  		}
&lt;span class="csLineNumber"&gt; 14:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;catch&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 15:&lt;/span&gt;  		{
&lt;span class="csLineNumber"&gt; 16:&lt;/span&gt;  		}
&lt;span class="csLineNumber"&gt; 17:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt; 18:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;ExecuteTryCatch()&lt;/h2&gt;
&lt;p&gt;Druga z metod również tyczy się wyjątków. Ona z kolei ma skrócić taki kod:&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;try&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	CanThrow();
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  &lt;span class="csKeyword"&gt;catch&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  	Hilfe();
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  &lt;span class="csKeyword"&gt;try&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 10:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 11:&lt;/span&gt;  	WillPossiblyThrowException();
&lt;span class="csLineNumber"&gt; 12:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt; 13:&lt;/span&gt;  &lt;span class="csKeyword"&gt;catch&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 14:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 15:&lt;/span&gt;  	Rollback();
&lt;span class="csLineNumber"&gt; 16:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt; 17:&lt;/span&gt;  &lt;span class="csKeyword"&gt;try&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 18:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 19:&lt;/span&gt;  	ShouldNotThrowButWhoKnows();
&lt;span class="csLineNumber"&gt; 20:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt; 21:&lt;/span&gt;  &lt;span class="csKeyword"&gt;catch&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 22:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 23:&lt;/span&gt;  	Log();
&lt;span class="csLineNumber"&gt; 24:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;W efekcie uzyskamy tylko 3 linijki - pozbywamy się ohydnej "rozwlekłości" nie tracąc jednocześnie czytelności! (z tą czytelnością pewnie nie wszyscy się zgodzą, ale... to kwestia przyzwyczajenia do lamd, zawsze można wstawić dodatkowy ENTER tu czy tam):&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  MethodWrappers.ExecuteTryCatch(CanThrow, Hilfe);
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  MethodWrappers.ExecuteTryCatch(WillPossiblyThrowException, Rollback);
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  MethodWrappers.ExecuteTryCatch(ShouldNotThrowButWhoKnows, Log);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Kod ową rozwlekłość w sobie bohatersko zatrzymujący:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// Executes the &amp;lt;paramref name=&amp;quot;tryOperation&amp;quot;/&amp;gt; and performs the &amp;lt;paramref name=&amp;quot;catchOperation&amp;quot;/&amp;gt; in case of exception.&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;param name=&amp;quot;tryOperation&amp;quot;&amp;gt;Operation to be executed.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;param name=&amp;quot;catchOperation&amp;quot;&amp;gt;Operation to be executed in case of exception.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  &lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;static&lt;/span&gt; &lt;span class="csKeyword"&gt;void&lt;/span&gt; ExecuteTryCatch(Action tryOperation, Action catchOperation)
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;try&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt; 10:&lt;/span&gt;  		tryOperation();
&lt;span class="csLineNumber"&gt; 11:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt; 12:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 13:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;catch&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 14:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt; 15:&lt;/span&gt;  		catchOperation();
&lt;span class="csLineNumber"&gt; 16:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt; 17:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;AggregateResults()&lt;/h2&gt;
&lt;p&gt;Kolejny kodoskracacz służy już do czegoś z wyjątkami niezwiązanego. Bardziej nawet kładę w nim nacisk na czytelność kodu niż na jego ilość. Zobaczmy PRZED:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  List&amp;lt;&lt;span class="csKeyword"&gt;int&lt;/span&gt;&amp;gt; positiveResults = &lt;span class="csKeyword"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="csKeyword"&gt;int&lt;/span&gt;&amp;gt;();
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  &lt;span class="csKeyword"&gt;int&lt;/span&gt; temp = FirstOperationReturningInt();
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  &lt;span class="csKeyword"&gt;if&lt;/span&gt; (temp &amp;gt;= 0)
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	positiveResults.Add(temp);
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  temp = Sum(1, 2);
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  &lt;span class="csKeyword"&gt;if&lt;/span&gt; (temp &amp;gt;= 0)
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  	positiveResults.Add(temp);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Cóż nas zatem interesuje? Chcemy mieć wyniki działania wszystkich metod zebrane w jednej kolekcji. ALE! Wyniki ujemne odrzucamy. Zbyt wiele razy miałem do czynienia z wyżej pokazanym kodem, czy nie ładniej tak?:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  List&amp;lt;&lt;span class="csKeyword"&gt;int&lt;/span&gt;&amp;gt; positiveResults = MethodWrappers.AggregateResults(
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  	number =&amp;gt; number &amp;gt;= 0,
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	FirstOperationReturningInt,
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	() =&amp;gt; Sum(1, 2)
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  	);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Najpierw definiujemy warunek, czyli JAKIE wartości mają być zapamiętywane, a potem listujemy operacje do wykonania. Nie wiem jak wam, ale mi się podoba. Kod:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// Executes each operation and creates an array of their results if.&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// Only results that satisfy a given condition are aggregated.&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;typeparam name=&amp;quot;T&amp;quot;&amp;gt;Type of a value returned by each of the actions.&amp;lt;/typeparam&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;param name=&amp;quot;condition&amp;quot;&amp;gt;Condition that must be satisfied for the result to be aggregated.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  &lt;span class="csDocumentation"&gt;/// &amp;lt;param name=&amp;quot;operations&amp;quot;&amp;gt;Array of aggregated results of the operations.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  &lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;static&lt;/span&gt; List&amp;lt;T&amp;gt; AggregateResults&amp;lt;T&amp;gt;(Predicate&amp;lt;T&amp;gt; condition, &lt;span class="csKeyword"&gt;params&lt;/span&gt; Func&amp;lt;T&amp;gt;[] operations)
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt; 10:&lt;/span&gt;  	List&amp;lt;T&amp;gt; results = &lt;span class="csKeyword"&gt;new&lt;/span&gt; List&amp;lt;T&amp;gt;(operations.Length);
&lt;span class="csLineNumber"&gt; 11:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 12:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;foreach&lt;/span&gt; (&lt;span class="csKeyword"&gt;var&lt;/span&gt; operation &lt;span class="csKeyword"&gt;in&lt;/span&gt; operations)
&lt;span class="csLineNumber"&gt; 13:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt; 14:&lt;/span&gt;  		T result = operation();
&lt;span class="csLineNumber"&gt; 15:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;if&lt;/span&gt; (condition == &lt;span class="csKeyword"&gt;null&lt;/span&gt; || condition(result))
&lt;span class="csLineNumber"&gt; 16:&lt;/span&gt;  			results.Add(result);
&lt;span class="csLineNumber"&gt; 17:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt; 18:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 19:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;return&lt;/span&gt; results;
&lt;span class="csLineNumber"&gt; 20:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Przytoczona lista nie jest imponująco długa, nie o to jednak chodzi. Chodzi o ideę, o eksperymentowanie, o estetykę... Niechaj nasz kod nie powoduje chęci odwiedzin u &lt;a href="http://www.compulsiveovereatingdisorder.com/images/bulimia_nervosa/bulimia_nervosa_250x251.jpg" target="_blank"&gt;porcelanowego bożka&lt;/a&gt;!&lt;br /&gt;
Mam nadzieję, że w komentarzach zobaczymy więcej przykładów. Mam również nadzieję, że moja krucjata o nauczenie się C# 3.0 przez tych, którzy się go boją, przynosi efekty!&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=2379" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/.net+3.5/default.aspx">.net 3.5</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/c_2300_/default.aspx">c#</category></item><item><title>Zawód - programista. Nadzieje.</title><link>http://zine.net.pl/blogs/procent/archive/2008/11/06/zaw-d-programista-nadzieje.aspx</link><pubDate>Wed, 05 Nov 2008 23:53:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:2335</guid><dc:creator>Procent</dc:creator><slash:comments>17</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/2335.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=2335</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=2335</wfw:comment><description>&lt;p&gt;Kilka miesięcy temu napisałem posta o jakże wdzięcznym tytule &lt;a href="http://www.maciejaniserowicz.com/post/2008/05/12/Jak-zostac-programista.aspx"&gt;"Jak zostać programistą"&lt;/a&gt;. Efekt tej minipublikacji przeszedł moje najśmielsze oczekiwania - liczba jej odwiedzin, mnogość komentarzy pod wpisem oraz prywatnych maili dotyczących poruszonej tematyki utrzymuje się do dziś na ponadprzeciętnym jak dla mnie poziomie. Wejścia na mojego bloga z Google po wpisaniu frazy "chcę zostać programistą" lub "zawód programisty" biją na głowę te wszystkie świetne wypociny:) o C#, VS czy .NET. Na forum CodeGuru raz po raz także ktoś rozpoczyna podobny wątek.&lt;br&gt;
W obliczu tak wielkiego zainteresowania postanowiłem zostawić na chwilę kwestie techniczne i rozwinąć trochę ów temat. Zagłębić się dalej w... "zawód programisty".&lt;br&gt;
Dzisiaj napiszę o nadziejach. Jak postrzegałem ten zawód wybierając go? Na co liczyłem zarywając noce przez ostatnie kilka lat? Nieustannie szukając swojego miejsca i chłonąc nową wiedzę? Mieszając życie prywatne z zawodowym tak, że teraz nie da się już ich rozerwać? Czego oczekiwałem od codziennej PRACY czyniąc z niej swoje hobby, swoją pasję i swój największy nałóg?&lt;/p&gt;
&lt;hr class="half"&gt;
&lt;h2&gt;Rozwój&lt;/h2&gt;
&lt;p&gt;Od samego początku przygody z programowaniem wiedziałem, że za tymi bełkotliwymi dla zwykłego człowieka milionami linii instrukcji kryje się coś więcej. Coś więcej niż przeciętne rzemiosło, polegające na nieustannym bezmyślnym klepaniu tego samego przez X godzin dziennie "aż w końcu zacznie działać".&lt;br&gt;
W przypadkach wyjątkowych można nawet pokusić się o określenie: SZTUKA. Do tego dążyłem i dążę cały czas. Upragnionego poziomu nigdy nie osiągnę, ale w tym przypadku od dotarcia do celu ważniejsza jest droga do niego.&lt;br&gt;
Przez większość studiów czekałem na ich koniec, żeby nareszcie móc bez przeszkód robić to co chcę. Iść do pracy i rozwijać swoje hobby, czy to nie cudowne i godne pozazdroszczenia? Od pracy zawodowej oczekiwałem  nieustannego, dynamicznego, pasjonującego poszerzania swojej wiedzy. Uczyć się od mistrzów, odkrywać jak wiele jeszcze nie wiem i nadrabiać te zaległości!&lt;/p&gt;
&lt;h2&gt;Kasa&lt;/h2&gt;
&lt;p&gt;Ileż to mówi się o zarobkach informatyków! Kończysz studia, całymi dniami robisz to co chcesz robić, i jeszcze za to płacą jak mało komu! Brzmi znajomo? Trąbią o tym w gazetach i internecie, szczególnie pod koniec każdego roku akademickiego. Po latach dziadowania wreszcie będę miał komputer taki jaki chcę, wreszcie kupię wymarzoną furę, wreszcie odwieczny problem "kino czy browar?" odejdzie w niepamięć! Tak sobie właśnie myślałem, to miała być prawdziwa wymierna nagroda.&lt;/p&gt;
&lt;h2&gt;Kariera&lt;/h2&gt;
&lt;p&gt;Hej, po co podczas studiów wychodzę daleeeeko poza standardowy program olewając to, co &lt;strong&gt;jest zbędne&lt;/strong&gt;? No jak to, oczywiste - żeby pracę zacząć od poziomu wyższego niż pierwszy lepszy absolwent, który cały czas od matury do magistra spędził z bełtem w garści. Skończę uczelnię i wyląduję na stanowisku programisty z prawdziwymi obowiązkami, nie będę jednym z miliona pospolitych zbieraczy programistycznej bawełny, "przynieś-podaj-pozamiataj". Raz dwa, miesiąc po miesiącu, kwartał po kwartale, coraz ambitniejsze zadania i coraz ciekawsze wyzwania. Przecież mam tyle do zaoferowania! Czyż nie o to w tym chodzi? Żeby nie popaść w rutynę, żeby się, o zgrozo, nie &lt;strong&gt;nudzić&lt;/strong&gt;! (czy w ogóle można się nudzić będąc programistą?)&lt;/p&gt;
&lt;h2&gt;Społeczności&lt;/h2&gt;
&lt;p&gt;Nic mi nie wiadomo o potajemnych spotkaniach prawników czy lekarzy, którzy po godzinach schodzą się w celu wymiany doświadczeń i wzajemnego dokształcania. Wiadomo mi natomiast o takich spotkaniach w środowiskach informatycznych. Czy to specyfika naszego zawodu, że jest on hobby dla którego jest się gotowym po całym dniu pracy siedzieć kolejne 3-4 godziny wśród podobnych sobie zapaleńców? Wszystko dla nowej wiedzy. Nieważne czy w aktualnym projekcie jest to potrzebne, nieważne czy są w ogóle rzeczywiste perspektywy na wykorzystanie omawianych narzędzi. Ważne, żeby wiedzieć co w trawie piszczy!&lt;br&gt;
Kolejna zatem nadzieja: "po studiach to dopiero się pokażę!" Przed prawdziwym rasowym programistą nie ma granic. Zdobyć tonę doświadczenia w pracy a następnie dzielić się nim na forum. Spotkać polskiego &lt;a href="http://ayende.com/blog/"&gt;Ayende&lt;/a&gt;, polskiego &lt;a href="http://blog.jpboodhoo.com/"&gt;Boodhoo&lt;/a&gt;, polskiego &lt;a href="http://www.hanselman.com/blog/"&gt;Hanselmana&lt;/a&gt;! Po studiach, w końcu na studentów "na pewno zawsze patrzy się z lekkim przymrużeniem oka"...&lt;/p&gt;
&lt;h2&gt;Pasja&lt;/h2&gt;
&lt;p&gt;Na koniec najważniejsze oczekiwanie - na każdym kroku, niezależnie od miejsca pracy, niezależnie od firmy, spotykać pasjonatów, dla których pokonywanie kolejnych barier jest esencją tego zawodu. Dyskusje o nowościach, wymiana doświadczeń, wyprawy na konferencje, być może nawet wspólna lektura blogów czy oglądanie DNRTV... czy to możliwe, że gdzieś tego nie ma? Czy nie po to buduje się zespoły? Przecież na pewno programista wstaje rano pełen energii, pewien, że dzisiaj będzie bardziej interesujące niż wczoraj i mniej interesujące niż jutro. Piękne?&lt;/p&gt;
&lt;hr class="half"&gt;
&lt;p&gt;Uff... Temat to bardzo dla mnie trudny. Dwa dni zabrało mi spisanie tego tak, aby móc to umieścić gdzieś poza własną głową. Podkreślam jeszcze raz, że zawarłem tu pewną część swoich myśli sprzed kilkunastu miesięcy, i wcześniej, identyfikując się z "tymi na rozdrożu". Kiedyś prawdopodobnie postaram się skonfrontować to z rzeczywistością. Kiedyś. Do tej pory jakiekolwiek dywagacje "co jest a co nie jest jak powinno" są bez sensu.&lt;/p&gt;
&lt;p&gt;A Wy, jak widzicie ten zawód? Jak go sobie wyobrażacie lub czym on jest dla Was? Który z wymienionych przeze mnie punktów jest naiwny, niepotrzebny, a czego zapomniałem tu dodać? Liczę na feedback, który pozwoli wszystkim dowiedzieć się więcej o znaczeniu słowa "programista". A może nawet szerzej - "informatyk"?&lt;/p&gt;
&lt;p&gt;Na koniec krótki przekaz do licealistów/studentów szukających motywacji do dalszej pracy nad sobą:
Przeczytajcie jeszcze raz to co spisałem. Porównajcie z własną odpowiedzią na pytanie "po co robię to co robię?" (ale ze mnie kiepski raper). Jeżeli choć częściowo pokrywa się z moją to... do roboty! To JEST możliwe. Nikt nie da na to gwarancji (a już na pewno nie ja ;) ). Nie każdemu uda się osiągnąć taki trwający całe życie programistyczny orgazm. Ale może akurat TY będziesz takim szczęśliwcem? Bez &lt;a href="http://www.hobotraveler.com/blogphotos01/207-44-ox-plow-nepal.jpg"&gt;pracy&lt;/a&gt; nie ma &lt;a href="http://www.potrawyregionalne.pl/media/agroprom/nkdz_4.jpg"&gt;kołaczy&lt;/a&gt;, a jedynie &lt;a href="http://www.spraguephoto.com/stock/images/7000_7499/7110%20Faces%20China%20Old%20woman%20of%20Xinghe%20village%20Shanxi%20Xian.jpg"&gt;mega-zmuła&lt;/a&gt;. Niechaj to będzie dla Was inspiracją.&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=2335" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/refleksje/default.aspx">refleksje</category></item><item><title>QueryStringValue w Web Client Software Factory</title><link>http://zine.net.pl/blogs/procent/archive/2008/10/20/querystringvalue-w-web-client-software-factory.aspx</link><pubDate>Mon, 20 Oct 2008 17:36:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:2253</guid><dc:creator>Procent</dc:creator><slash:comments>0</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/2253.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=2253</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=2253</wfw:comment><description>&lt;p&gt;Web Client Software Factory udostępnia bardzo ciekawy i przydatny mechanizm komunikacji ze stanem przechowywanym w sesji. W poniższym przykładzie podczas tworzenia obiektu do pola zostanie wstrzyknięta odpowiednia wartość pobrana z sesji:&lt;/p&gt;

&lt;div style="color:#fff;line-height:12px;font-family:Consolas, Courier;background-color:#333;word-wrap:break-word;"&gt;
&lt;pre&gt;
&lt;span style="color:#2B91AF;"&gt;  1:&lt;/span&gt;  &lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;class&lt;/span&gt; MyClass
&lt;span style="color:#2B91AF;"&gt;  2:&lt;/span&gt;  {
&lt;span style="color:#2B91AF;"&gt;  3:&lt;/span&gt;  	[SessionStateKey(&lt;span style="color:#E0551D;"&gt;&amp;quot;MyNumber&amp;quot;&lt;/span&gt;)]
&lt;span style="color:#2B91AF;"&gt;  4:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; StateValue&amp;lt;&lt;span style="color:#00aaff;"&gt;int&lt;/span&gt;&amp;gt; MyNumber;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Do wartości tej dostać się można następująco:&lt;/p&gt;

&lt;div style="color:#fff;line-height:12px;font-family:Consolas, Courier;background-color:#333;word-wrap:break-word;"&gt;
&lt;pre&gt;
&lt;span style="color:#2B91AF;"&gt;  1:&lt;/span&gt;  &lt;span style="color:#00aaff;"&gt;int&lt;/span&gt; number = MyNumber.Value;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Wszystko za sprawą Object Buildera. Jakie korzyści płyną z zastosowania takiego rozwiązania? Oprócz ustandaryzowanego i prostego sposobu wykorzystania sesji najważniejsza jest możliwość przeprowadzenia testów jednostkowych na obiektach polegających na wartościach pobieranych z sesji.&lt;/p&gt;
&lt;p&gt;Ale ja nie do końca o tym chciałem... Kilka tygodni temu &lt;a href="http://zine.net.pl/blogs/jakubin/" target="_blank"&gt;Kuba Binkowski&lt;/a&gt; w swoim &lt;a href="http://ms-groups.pl/wg.net/31_spotkanie/default.aspx?InstanceID=1" target="_blank"&gt;wystąpieniu na wg.net&lt;/a&gt; pokazał podobne rozwiązanie w &lt;a href="http://www.codeplex.com/unity" target="_blank"&gt;Unity&lt;/a&gt;, tyle że pobierające wartość z URL. No i właśnie coś takiego dodamy za chwilę do WCSF.&lt;/p&gt;
&lt;hr class="half"&gt;
&lt;p&gt;Cały proces rozpoczyna się od odpalenia Reflectora i analizy szczegółów implementacyjnych StateValue, ponieważ funkcjonalność będzie praktycznie ta sama. A potem - sam miód, czyli implementacja. Zatem po kolei, do dzieła!&lt;/p&gt;
&lt;p&gt;1. Pierwszy krok to utworzenie interfejsu analogicznego do IStateValue. Interfejs ten zdefiniuje nam kontrakt komunikacyjny pomiędzy naszym systemem a URLem i będzie prawie taki sam jak wspomniane IStateValue. Jedyna różnica to typ zwracany przez właściwość Value. W naszym przypadku będzie to &lt;em&gt;string&lt;/em&gt;, ponieważ to właśnie możemy z URLa wyciągnąć. Dodatkowo należy zwrócić uwagę na właściwość Request - nie wołamy bezpośrednio HttpContext.Current.Request. Zamiast tego uzupełnimy tą wartość później, korzystając z innych mechanizmów dostępnych w WCSF.&lt;/p&gt;

&lt;div style="color:#fff;line-height:12px;font-family:Consolas, Courier;background-color:#333;word-wrap:break-word;"&gt;
&lt;pre&gt;
&lt;span style="color:#2B91AF;"&gt;  1:&lt;/span&gt;  &lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;interface&lt;/span&gt; IQueryStringValue
&lt;span style="color:#2B91AF;"&gt;  2:&lt;/span&gt;  {
&lt;span style="color:#2B91AF;"&gt;  3:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;string&lt;/span&gt; KeyName { get; set; }
&lt;span style="color:#2B91AF;"&gt;  4:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;string&lt;/span&gt; Value { get; }
&lt;span style="color:#2B91AF;"&gt;  5:&lt;/span&gt;  	HttpRequest Request { get; set; }
&lt;span style="color:#2B91AF;"&gt;  6:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;2. Następnie wypada interfejs ów zaimplementować. Tworzona klasa będzie wykorzystywać typ ogólny, dzięki czemu uzyskamy możliwość konwersji z ciągu znaków do liczby czy daty bez ingerencji końcowego programisty.&lt;/p&gt;

&lt;div style="color:#fff;line-height:12px;font-family:Consolas, Courier;background-color:#333;word-wrap:break-word;"&gt;
&lt;pre&gt;
&lt;span style="color:#2B91AF;"&gt;  1:&lt;/span&gt;  &lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;class&lt;/span&gt; QueryStringValue&amp;lt;T&amp;gt; : IQueryStringValue
&lt;span style="color:#2B91AF;"&gt;  2:&lt;/span&gt;  {
&lt;span style="color:#2B91AF;"&gt;  3:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;string&lt;/span&gt; KeyName { get; set; }
&lt;span style="color:#2B91AF;"&gt;  4:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt;  5:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; HttpRequest Request { get; set; }
&lt;span style="color:#2B91AF;"&gt;  6:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt;  7:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;string&lt;/span&gt; IQueryStringValue.Value
&lt;span style="color:#2B91AF;"&gt;  8:&lt;/span&gt;  	{
&lt;span style="color:#2B91AF;"&gt;  9:&lt;/span&gt;  		get { &lt;span style="color:#00aaff;"&gt;return&lt;/span&gt; Request.QueryString[KeyName]; }
&lt;span style="color:#2B91AF;"&gt; 10:&lt;/span&gt;  	}
&lt;span style="color:#2B91AF;"&gt; 11:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt; 12:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; T Value
&lt;span style="color:#2B91AF;"&gt; 13:&lt;/span&gt;  	{
&lt;span style="color:#2B91AF;"&gt; 14:&lt;/span&gt;  		get
&lt;span style="color:#2B91AF;"&gt; 15:&lt;/span&gt;  		{
&lt;span style="color:#2B91AF;"&gt; 16:&lt;/span&gt;  			&lt;span style="color:#00aaff;"&gt;var&lt;/span&gt; v = ((IQueryStringValue)&lt;span style="color:#00aaff;"&gt;this&lt;/span&gt;).Value;
&lt;span style="color:#2B91AF;"&gt; 17:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt; 18:&lt;/span&gt;  			&lt;span style="color:#00aaff;"&gt;if&lt;/span&gt; (&lt;span style="color:#00aaff;"&gt;string&lt;/span&gt;.IsNullOrEmpty(v))
&lt;span style="color:#2B91AF;"&gt; 19:&lt;/span&gt;  				&lt;span style="color:#00aaff;"&gt;return&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;default&lt;/span&gt;(T);
&lt;span style="color:#2B91AF;"&gt; 20:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt; 21:&lt;/span&gt;  			&lt;span style="color:#00aaff;"&gt;return&lt;/span&gt; (T)Convert.ChangeType(v, T);
&lt;span style="color:#2B91AF;"&gt; 22:&lt;/span&gt;  		}
&lt;span style="color:#2B91AF;"&gt; 23:&lt;/span&gt;  	}
&lt;span style="color:#2B91AF;"&gt; 24:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;3. Mamy już strukturę potrzebną do przechowywania danych pobranych z QueryStringa. Zauważmy jednak, że brakuje jeszcze odpowiednika atrybutu SessionStateKey będącego znakiem dla ObjectBuildera że w tym miejscu należy się zatrzymać i "coś zrobić". Implementacja takiego oznaczenia jest banalnie prosta, ponieważ tak naprawdę jedyne czego potrzebujemy to klucz pod którym należy szukać żądanej wartości:&lt;/p&gt;

&lt;div style="color:#fff;line-height:12px;font-family:Consolas, Courier;background-color:#333;word-wrap:break-word;"&gt;
&lt;pre&gt;
&lt;span style="color:#2B91AF;"&gt;  1:&lt;/span&gt;  [AttributeUsage(AttributeTargets.Field, Inherited = &lt;span style="color:#00aaff;"&gt;false&lt;/span&gt;, AllowMultiple = &lt;span style="color:#00aaff;"&gt;false&lt;/span&gt;)]
&lt;span style="color:#2B91AF;"&gt;  2:&lt;/span&gt;  &lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;sealed&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;class&lt;/span&gt; QueryStringKeyAttribute : Attribute
&lt;span style="color:#2B91AF;"&gt;  3:&lt;/span&gt;  {
&lt;span style="color:#2B91AF;"&gt;  4:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;string&lt;/span&gt; QueryStringKey { get; &lt;span style="color:#00aaff;"&gt;private&lt;/span&gt; set; }
&lt;span style="color:#2B91AF;"&gt;  5:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt;  6:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; QueryStringKeyAttribute(&lt;span style="color:#00aaff;"&gt;string&lt;/span&gt; queryStringKey)
&lt;span style="color:#2B91AF;"&gt;  7:&lt;/span&gt;  	{
&lt;span style="color:#2B91AF;"&gt;  8:&lt;/span&gt;  		QueryStringKey = queryStringKey;
&lt;span style="color:#2B91AF;"&gt;  9:&lt;/span&gt;  	}
&lt;span style="color:#2B91AF;"&gt; 10:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;4. Zatrzymajmy się na chwilę i spójrzmy co już napisaliśmy. Cała instrastruktura konieczna do wykorzystania mechanizmu jest gotowa. W akcji będzie to wyglądać tak:&lt;/p&gt;

&lt;div style="color:#fff;line-height:12px;font-family:Consolas, Courier;background-color:#333;word-wrap:break-word;"&gt;
&lt;pre&gt;
&lt;span style="color:#2B91AF;"&gt;  1:&lt;/span&gt;  	[QueryStringkey(&lt;span style="color:#E0551D;"&gt;&amp;quot;MyNumber&amp;quot;&lt;/span&gt;)]
&lt;span style="color:#2B91AF;"&gt;  2:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;private&lt;/span&gt; QueryStringValue&amp;lt;&lt;span style="color:#00aaff;"&gt;int&lt;/span&gt;&amp;gt; SomeNumber;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;...przy czym obsługiwany URL to http://www.xxx.com/yyy.aspx?MyNumber=666.&lt;br /&gt;
Ale to oczywiście nie koniec. Nigdzie jeszcze fizycznie nie dobieramy się do adresu, nigdzie nie wciskamy się w proces tworzenia obiektu przez ObjectBuilder! Kroczmy zatem dalej ścieżką prawych i sprawiedliwych. Jesteśmy blisko!&lt;/p&gt;
&lt;p&gt;5. Teraz czeka nas najtrudniejsze zadanie - musimy napisać własną strategię ObjectBuildera, która powypełnia wszystkie pola oznaczone tym ślicznym atrybutem. Bez kilkukrotnego zerknięcia do Reflectora na implementację &lt;em&gt;SessionStateBindingStrategy&lt;/em&gt; się nie obejdzie, ale w końcu po coś to narzędzie mamy, prawda? Tak więc wykonujemy wszystkie konieczne czynności, które ot tak wymienię jedna po drugiej:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;za pomocą WCSFowego pojemnika IoC uzyskujemy instancję usługi, która dostarczy nam aktualny kontekst HTTP (a więc i obiekt HttpRequest)&lt;/li&gt;
&lt;li&gt;przejeżdżamy się po &lt;u&gt;wszystkich&lt;/u&gt; polach tworzonego obiektu pomijając te mające inny typ niż implementację naszego interfejsu IQueryStringValue&lt;/li&gt;
&lt;li&gt;z deklaracji w/w pól pobieramy instancję atrybutu QueryStringKey zawierającą klucz wskazujący na żądaną wartość w URLu (poniższa implementacja wyrzuci wyjątek, gdy pole takiego typu nie zostanie oznaczone takim atrybutem)&lt;/li&gt;
&lt;li&gt;wstawiamy w owo pole nowa instancję pożądanego typu, wypełniając jego właściwości przechowujące Key oraz Request&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;W tym momencie mamy już pole, którego właściwość Value zwróci nam to czego oczekujemy!&lt;/p&gt;

&lt;div style="color:#fff;line-height:12px;font-family:Consolas, Courier;background-color:#333;word-wrap:break-word;"&gt;
&lt;pre&gt;
&lt;span style="color:#2B91AF;"&gt;  1:&lt;/span&gt;  &lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;class&lt;/span&gt; QueryStringBindingStrategy : BuilderStrategy
&lt;span style="color:#2B91AF;"&gt;  2:&lt;/span&gt;  {
&lt;span style="color:#2B91AF;"&gt;  3:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;override&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;object&lt;/span&gt; BuildUp(IBuilderContext context, System.Type typeToBuild, &lt;span style="color:#00aaff;"&gt;object&lt;/span&gt; existing, &lt;span style="color:#00aaff;"&gt;string&lt;/span&gt; idToBuild)
&lt;span style="color:#2B91AF;"&gt;  4:&lt;/span&gt;  	{
&lt;span style="color:#2B91AF;"&gt;  5:&lt;/span&gt;  		IHttpContextLocatorService service = context.Locator.Get&amp;lt;IHttpContextLocatorService&amp;gt;(&lt;span style="color:#00aaff;"&gt;new&lt;/span&gt; DependencyResolutionLocatorKey(&lt;span style="color:#00aaff;"&gt;typeof&lt;/span&gt;(IHttpContextLocatorService), &lt;span style="color:#00aaff;"&gt;null&lt;/span&gt;));
&lt;span style="color:#2B91AF;"&gt;  6:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt;  7:&lt;/span&gt;  		&lt;span style="color:#00aaff;"&gt;if&lt;/span&gt; (service != &lt;span style="color:#00aaff;"&gt;null&lt;/span&gt;)
&lt;span style="color:#2B91AF;"&gt;  8:&lt;/span&gt;  		{
&lt;span style="color:#2B91AF;"&gt;  9:&lt;/span&gt;  			&lt;span style="color:#00aaff;"&gt;var&lt;/span&gt; httpContext = service.GetCurrentContext();
&lt;span style="color:#2B91AF;"&gt; 10:&lt;/span&gt;  			&lt;span style="color:#00aaff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#00aaff;"&gt;var&lt;/span&gt; field &lt;span style="color:#00aaff;"&gt;in&lt;/span&gt; typeToBuild.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
&lt;span style="color:#2B91AF;"&gt; 11:&lt;/span&gt;  			{
&lt;span style="color:#2B91AF;"&gt; 12:&lt;/span&gt;  				&lt;span style="color:#00aaff;"&gt;if&lt;/span&gt; (&lt;span style="color:#00aaff;"&gt;typeof&lt;/span&gt;(IQueryStringValue).IsAssignableFrom(field.FieldType) == &lt;span style="color:#00aaff;"&gt;false&lt;/span&gt;)
&lt;span style="color:#2B91AF;"&gt; 13:&lt;/span&gt;  					&lt;span style="color:#00aaff;"&gt;continue&lt;/span&gt;;
&lt;span style="color:#2B91AF;"&gt; 14:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt; 15:&lt;/span&gt;  				IQueryStringValue queryStringValue = (IQueryStringValue)Activator.CreateInstance(field.FieldType);
&lt;span style="color:#2B91AF;"&gt; 16:&lt;/span&gt;  				QueryStringKeyAttribute attribute = (QueryStringKeyAttribute)field.GetCustomAttributes(&lt;span style="color:#00aaff;"&gt;typeof&lt;/span&gt;(QueryStringKeyAttribute), &lt;span style="color:#00aaff;"&gt;false&lt;/span&gt;)[0];
&lt;span style="color:#2B91AF;"&gt; 17:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt; 18:&lt;/span&gt;  				queryStringValue.KeyName = attribute.QueryStringKey;
&lt;span style="color:#2B91AF;"&gt; 19:&lt;/span&gt;  				queryStringValue.Request = httpContext.Request;
&lt;span style="color:#2B91AF;"&gt; 20:&lt;/span&gt;  				field.SetValue(existing, queryStringValue);
&lt;span style="color:#2B91AF;"&gt; 21:&lt;/span&gt;  			}
&lt;span style="color:#2B91AF;"&gt; 22:&lt;/span&gt;  		}
&lt;span style="color:#2B91AF;"&gt; 23:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt; 24:&lt;/span&gt;  		&lt;span style="color:#00aaff;"&gt;return&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;base&lt;/span&gt;.BuildUp(context, typeToBuild, existing, idToBuild);
&lt;span style="color:#2B91AF;"&gt; 25:&lt;/span&gt;  	}
&lt;span style="color:#2B91AF;"&gt; 26:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Jeszcze jedna mała uwaga: powyższa implementacja pozwala na potraktowanie w ten sposób WSZYSTKICH, także prywatnych, pól. Dostępny w WCSF mechanizm można zastosować jedynie do pól publicznych. Powód? Linijka numer 10. Tutaj jawnie żądamy dostępu do pól publicznych i niepublicznych, podczas gdy implementacja strategii StateValue wykorzystuje bezparametryczną wersję metody GetFields() zwracającą jedynie publiczne pola.&lt;/p&gt;
&lt;p&gt;6. Został ostatni kroczek. Musimy powiedzieć ObjectBuilderowi że mamy o taki cudny mechanizm, który chcielibyśmy w proces tworzenia obiektów wprząc. Reflector w kilka chwil pokazuje nam w którą stronę gęby nasze należy zwrócić i co uczynić, aby było to możliwe. Rozwiązaniem jest własna klasa dziedzicząca z WebClientApplication nadpisująca jedną metodę:&lt;/p&gt;

&lt;div style="color:#fff;line-height:12px;font-family:Consolas, Courier;background-color:#333;word-wrap:break-word;"&gt;
&lt;pre&gt;
&lt;span style="color:#2B91AF;"&gt;  1:&lt;/span&gt;  &lt;span style="color:#00aaff;"&gt;public&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;class&lt;/span&gt; CustomWebApplication : WebClientApplication
&lt;span style="color:#2B91AF;"&gt;  2:&lt;/span&gt;  {
&lt;span style="color:#2B91AF;"&gt;  3:&lt;/span&gt;  	&lt;span style="color:#00aaff;"&gt;protected&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;override&lt;/span&gt; &lt;span style="color:#00aaff;"&gt;void&lt;/span&gt; AddBuilderStrategies(Microsoft.Practices.ObjectBuilder.IBuilder&amp;lt;WCSFBuilderStage&amp;gt; builder)
&lt;span style="color:#2B91AF;"&gt;  4:&lt;/span&gt;  	{
&lt;span style="color:#2B91AF;"&gt;  5:&lt;/span&gt;  		&lt;span style="color:#00aaff;"&gt;base&lt;/span&gt;.AddBuilderStrategies(builder);
&lt;span style="color:#2B91AF;"&gt;  6:&lt;/span&gt;  
&lt;span style="color:#2B91AF;"&gt;  7:&lt;/span&gt;  		builder.Strategies.AddNew&amp;lt;QueryStringBindingStrategy&amp;gt;(WCSFBuilderStage.Initialization);
&lt;span style="color:#2B91AF;"&gt;  8:&lt;/span&gt;  	}
&lt;span style="color:#2B91AF;"&gt;  9:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;A co dalej z tą klasą zrobić - było &lt;a href="http://www.maciejaniserowicz.com/post/2008/10/04/Autoryzacja-w-Web-Client-Software-Factory-z-wykorzystaniem-wyrazen-regularnych.aspx" target="_blank"&gt;ostatnio&lt;/a&gt;.&lt;/p&gt;
&lt;hr class="half"&gt;
&lt;p&gt;That's all folks!&lt;br /&gt;
Żeby nie było tak słodko dodam, że całą tą pracę wykonałem właściwie na marne. Po napisaniu owego rozwiązania wpisałem z ciekawości w Google "WCSF QueryStringValue" i... co się okazało? Istnieje sobie projekcik &lt;a href="http://www.codeplex.com/wcsfcontrib" target="_blank"&gt;WCSF Contrib&lt;/a&gt; i tam dokładnie takie samo rozwiązanie siedzi już od jakiegoś czasu. No ale, co się człowiek nauczy to jego.&lt;/p&gt;
&lt;p&gt;Jest też jeszcze jedna sprawa. W WCSF możemy wykorzystywać sesję (jak to brzmi...) również w inny sposób. Istnieje sobie atrybut StateDependency, dzięki któremu możemy podobne sztuczki robić z parametrami metod! To jednak dużo wyższa szkoła jazdy - bez zagłębienia się po uszy w kod źródłowy WCSF i jego modyfikacji się nie obejdzie. Zatem odpowiednik, czyli QueryStringDependency (którego już w WCSF Contrib nie uświadczymy, co jest absolutnie zrozumiałe jeśli się poprzednie zdanie jeszcze raz przeczyta), stworzymy sobie może innym razem.&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=2253" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/.net/default.aspx">.net</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/tools/default.aspx">tools</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/sample/default.aspx">sample</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/wcsf/default.aspx">wcsf</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/entlib/default.aspx">entlib</category></item><item><title>Relacja z MTS 2008</title><link>http://zine.net.pl/blogs/procent/archive/2008/10/10/relacja-z-mts-2008.aspx</link><pubDate>Fri, 10 Oct 2008 21:13:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:2137</guid><dc:creator>Procent</dc:creator><slash:comments>25</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/2137.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=2137</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=2137</wfw:comment><description>&lt;p&gt;W dniach 8-9 października w Pałacu Kultury i Nauki w Warszawie odbyła się wielka konferencja &lt;a href="http://www.mts2008.pl/" target="_blank"&gt;Microsoft Technology Summit 2008&lt;/a&gt;. Byłem. Widziałem. I, jak z &lt;a href="http://www.maciejaniserowicz.com/?tag=/relacje" target="_blank"&gt;większości wydarzeń w których uczestniczę&lt;/a&gt;, uwagi swe niniejszym przekazuję światu.&lt;/p&gt;
&lt;hr class="half"&gt;
&lt;h2&gt;Bloggers Underground&lt;/h2&gt;
&lt;p&gt;W wigilię MTS Aneta Sidorowicz, Karol Stilger i Łukasz Foks zorganizowali mały starter - spotkanie polskich bloggerów. Idea zaiste godna podziwu. Zainteresowanie i frekwencja - większa niż się spodziewałem! W kameralnej piwniczce lokalu Leżaki można było spotkać kilkadziesiąt osób prowadzących bądź zamierzających prowadzić bloga, pogadać przy piwku, posłuchać kilku wystąpień na przeróżne tematy. Super! Sam miałem wygłosić małe "przemówionko" na temat sensu prowadzenia bloga w moim rozumieniu, jednak (chyba na szczęście:) ) w ostatniej chwili się wycofałem. Wieczór jak najbardziej udany, brawo!&lt;/p&gt;
&lt;hr class="half"&gt;
&lt;h2&gt;MTS 2008 - Organizacja&lt;/h2&gt;
&lt;p&gt;O tym tylko kilka słów, bo moim zdaniem kwestie organizacyjne nie mają specjalnie znaczenia. Tłok, ścisk, kolejki po colę/kawę, smaczne kanapki, niesmaczny obiad, dłuuugie dystanse do pokonania między poszczególnymi sesjami. I to tyle, bez wnikania.  W końcu nie zjawiliśmy się tam żeby się najeść i odpocząć, tylko wysłuchać sesji i spotkać się z ludźmi, więc na utrudnienia takiej natury uwagi nie zwracam i nie narzekam. Aha, jednego mi brakowało: w plecaku wśród reklam dało się znaleźć długopis, ale zabrakło notatnika! Dwie małe stroniczki w przewodniku to zdecydowanie za mało jak na notatki z ośmiu sesji.&lt;/p&gt;
&lt;h2&gt;0. Sesja generalna&lt;/h2&gt;
&lt;p&gt;Powitanie podzielono na kilka części. Najpierw standardowa gadka jak to miło nas widzieć i jacy jesteśmy wspaniali. Następnie kilka(set) słów od najważniejszych sponsorów, czyli Intela i Della. No właśnie... Zdaję sobie sprawę, że zapewne "biznes" tego wymaga, że w jakiś sposób trzeba owych złotych sponsorów wyróżnić, ale czy aby na pewno przydługie "rozmowy w toku" w wykonaniu dyrektorów i słodzenie sobie nawzajem jest najlepszym sposobem na rozpoczęcie konferencji? Prześciganie się w rankingu "która korporacja posadziła w tym roku więcej drzew" może co najwyżej rozbawić:). Na szczęście drętwe tokszoł nie trwało zbyt długo i na scenie pojawił się Mariusz Jarzębowski z opowieścią o "Historii wstążki". Sam pomysł postawienia Ribbona w roli głównego bohatera wystąpienia może wydawać się... dziwny? Ha! Temat nie był mi jednak obcy, ponieważ niesamowicie pozytywne opinie o tej prezentacji czytałem już wcześniej w relacjach ze zlotu portalu dobreprogramy.pl. Opowiadał mi także o niej, również w samych superlatywach, "tajemniczy ktoś" oglądający ją wcześniej w innych okolicznościach. No i cóż mogę powiedzieć - oni wszyscy mieli rację! Prowadzone w luźnej atmosferze wystąpienie nie zawierało może wielkich wartości technicznych, ale z otwartymi ustami słuchało się doskonałego prelegenta opowiadającego o tym, jak to w 2003 roku Microsoft przejrzał na oczy i doszedł do wniosku że dotychczasowe menu SUX:). Rewelacja! Jeśli jest to część szerzej zakrojonej akcji zmiany wizerunku MS (a w świetle ostatnich reklamówek z Billem, i nie tylko, można tak domniemywać) to z mojej strony oklaski na stojąco. Jest to zdecydowanie dobra droga!&lt;/p&gt;
&lt;h2&gt;1. "Wydajne aplikacje ASP.NET w świecie Web 2.0" Tymoteusz Chmielewski&lt;/h2&gt;
&lt;p&gt;Jednak co tam jakaś wstążka, skoro już pierwsza prawdziwa sesja zapowiada się niesamowicie interesująco! Wydajność ASP.NET, poziom sesji 400 (czyli w moim rozumieniu: dla masta-wymiataczy). Jakby tego było mało - miałem w pamięci sesję panów z K2 sprzed roku, kiedy to na DevDays 2007 bardzo zgrabnie i ciekawie opowiadali o podstawach zabezpieczania aplikacji webowych.&lt;br /&gt;
Jak można wywnioskować - dwaj panowie (tylko jeden z nich jest wymieniony na stronie i slajdach, nazwiska drugiego niestety nie uchwyciłem) mieli przed sobą postawione nie lada wymagania. No i  się zaczęło. Najpierw krótkie wprowadzenie definiujące pojęcie Web 2.0 (na poziomie 400?), potem "co to jest CSS/XHTML, REST, RIA i web services" (na poziomie 400?). Krótka wymiana spojrzeń z sąsiadami i wszystko jasne - nie tylko ja jestem zaskoczony. No ale nic, to dopiero rozgrzewka... Panowie, pokażcie coś interesującego! Nadszedł czas na pierwsze demo... Dwa (pewnie nie w 100% wierne) cytaty:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"teraz przeciągnę na stronę ScriptManager - to takie coś dzięki czemu na naszej stronie będzie działał AJAX, nie będę wchodził w szczegóły"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"ta dziwna składnia którą Państwo widzą to LINQ, ale o tym nie będziemy dziś mówić, muszą nam Państwo uwierzyć że to działa"&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Czy trzeba pisać coś więcej? Chyba nie.&lt;br&gt;
Ale napiszę. Dalsza część niestety nie była lepsza. Teksty wszystkowiedzącym tonem w stylu "nie będziemy się pastwić nad pewnym portalem społecznościowym którego serwery nie wytrzymały" na tle prezentacji na TAKIM poziomie naprawdę nie były na miejscu. Omawianie PRODUKTU Community Server na sesji mającej pokazać jak TWORZYĆ wydajne aplikacje też nie jest doskonałym pomysłem. Ale jeśli nawet taka była koncepcja, to co oznacza sformułowanie "CS ma blogi, fora, wiki, ale pomimo swojego rozbudowania nie ma CMSa - dodaliśmy do niego możliwość edycji artykułów"?  Zine stoi na Community Server sprzed kilku lat, a nie zauważyłem tam braku możliwości edycji czegokolwiek. Chyba że coś mi się kompletnie pomieszało - tylko co?&lt;br&gt;
To jednak nie wszystko... Nie chce mi już się nawet opisywać wynoszenia pod niebiosa Linq To Sql jako najnajnajkochańszego O/R Mappera (z pominięciem faktu, że nie jest to O/R Mapper "z prawdziwego zdarzenia" i że to Linq To Entities ma konkurować z takim na przykład NHibernate) czy masakrycznie tendencyjnych testów wydajności Linq To Sql vs DataSet vs DataReader podczas wyświetlania stronicowanych danych. Zamiast tego podzielę się innym faktem, który wcisnął mnie w fotel i jest głównym powodem tak emocjonalnej reakcji na wszystko co nam przedstawiono. Fakt ten to: "ASP.NET AJAX pozwala nam bardzo odciążyć serwer i zwiększyć jego wydajność, ponieważ po wrzuceniu strony w Update Panel nie musi on się zajmować całym cyklem życia strony". Wiedzieliście o tym? To chyba najbardziej nagłośniony MIT o UpdatePanel i uwagę na to zwraca się na każdym kroku - UpdatePanel nie powoduje zmian w cyklu życia strony! Bez jaj, takie kwiatki na takiej konferencji zdarzać się po prostu NIE POWINNY. Przecież ludzie zapłacili żeby tu wejść! W tym momencie wszystkie zmanierowane wypowiedzi utraciły jak dla mnie resztki "profesjonalizmu" i stały się jedynie czczymi wyssanymi z palca niby-faktami powstałymi w procesie "jestem przekonany, że....".&lt;br&gt;
No dobra, dosyć, wykorzystując cytowany fragment: przestaję się pastwić. Dotrwałem do końca i żyję, ciekawe jednak w ilu środowiskach produkcyjnych taka "wiedza" znajdzie zastosowanie. A no bo przecież "na konferencji panowie mówili że tak jest lepiej"...&lt;/p&gt;
&lt;p&gt;&lt;STRONG&gt;Ocena: &lt;FONT color="#ff0000"&gt;2&lt;/FONT&gt;&lt;/STRONG&gt; (nie 1, bo przykład SSO pomiędzy własną stroną a CS był całkiem fajny).&lt;/p&gt;
&lt;h2&gt;2. "Praktyczne aspekty budowania rozwiazań klasy Enterprise z wykorzystaniem produktów Microsoft Patterns and Practices" Marcin Sieradzki&lt;/h2&gt;
&lt;p&gt;Po tak katastrofalnym falstarcie apetyt jeszcze bardziej się zwiększył. Ponownie poziom 400, a do tego połączenie słów "praktyczne" i "Patterns and Practices" w temacie! Przyznać muszę, że dokumentację EntLib przeczytałem całą, bawiłem się też przykładami, próbowałem sam "co nieco" na własnych mini-poligonach, wszelakich webcastów naoglądałem się również co niemiara. Teorią o Entlibie wyładowany więc jestem po brzegi. A praktyka... No właśnie, łapanie wyjątków i logowanie to sobie można poćwiczyć w domu, ale jak naprawdę sprawuje się cała reszta w warunkach bojowych? Tego chciałem się dowiedzieć - na jakie miny uważać?&lt;br /&gt;
Sesja rozpoczęła się pozytywnie - tu żarcik, tam dowcip, w międzyczasie pobieżne omówienie architektury EntLiba. Prelegent zaznaczył, że nie jest zawodowym zwierzęciem scenicznym. Było widać pewien brak swobody, ale w niczym to nie przeszkadzało. Jak więc potoczyły się dalsze losy naszego spotkania?&lt;br /&gt;
Tutaj musiałem na chwilę zrobić przerwę i się głęboko zastanowić. Bo czego tak naprawdę dowiedziałem się podczas tych 75 minut? Chyba tylko tego co następuje: jest sobie w Sygnity jakaś firma która tworzy program Documan; na jednym ze slajdów mogłem zobaczyć (tzn mógłbym gdyby ekran był 10x większy) diagram klas części owego systemu; na sali siedział Piotrek który projektował raporty (WTF???); w systemie wykorzystano EntLib. Naprawdę mimo najszczerszych chęci nie przypominam sobie żadnych wartościowych wskazówek dotyczących PRAKTYCZNEGO wykorzystania tych bibliotek, wykraczających poza najprostsze demo. Pewnie dlatego, że w połowie agendy skończył się czas... Owszem, rady dotyczące książek i innych ładnie skatalogowanych źródeł wiedzy niosą za sobą sporą wartość. Ale w temacie było napisane wyraźnie: PRAKTYCZNE. Praktyki nie doświadczyliśmy. A wielka szkoda, bo właśnie skończyłem czytać ściągniętą ze stron MTS prezentację i mogło być bardzo udanie... Ale z drugiej strony - można było to przewidzieć, skoro prezentacja ma 98 (sic!) POTĘŻNYCH slajdów na 75 minut.&lt;/p&gt;
&lt;p&gt;&lt;STRONG&gt;Ocena: &lt;FONT color="#ff0000"&gt;4&lt;/FONT&gt;&lt;/STRONG&gt; (bo się naprawdę nieźle zapowiadało...).&lt;/p&gt;
&lt;h2&gt;3. ".NET bez wizardów – sposoby tworzenia i dynamicznego aktywowania komponentów w aplikacjach" Bartosz Pampuch&lt;/h2&gt;
&lt;p&gt;Pół dnia minęło i co? I - za przeproszeniem - jajco. Porządnie sfrustrowany skierowałem się do kolejnej sali. Szedłem jednak spokojny, wiedziałem że będzie zajebiście. Na prezentacjach Bartka zawsze jest zajebiście. Jego energia, pasja i NIEWYOBRAŻALNE wręcz przygotowanie do sesji zwalają z nóg. Zanim przejdę dalej napiszę tylko w skrócie: jak było? oczywiście-zajebiście:)&lt;br&gt;
Ciężko w jednym zdaniu zmieścić cały zakres omawianej prelekcji. Tytuł ".NET bez wizardów" jest troszkę mylący. Nie było tam recepty "jak napisać program bez wizarda". Przejechaliśmy się za to po bardzo wielu różnych materiach - od teorii tworzenia oprogramowania (zasady takie jak Separation of concerns czy Don't repeat yourself) przez Dependency Injection aż po programowanie aspektowe. Zajrzeliśmy do wszystkich liczących się pojemników IoC (m.in. Castle, Unity, Ninject, Spring.NET). Dowiedzieliśmy się jakie są miedzy nimi różnice, co każdy z nich oferuje unikalnego, jak z ich wydajnością. AOP także zaprezentowano nam profesjonalnie - zobaczyliśmy dema możliwości gołego .NETa w tym zakresie (Context Bound Object) oraz PostSharpa. Wielka szkoda że póki co prezentacja nie jest dostępna do ściągnięcia, mam nadzieję że w jakiejś postaci pojawi się na stronce. Dlaczego tak enigmatycznie - "w jakiejś postaci", a nie jak wszystkie inne w pptx?&lt;br&gt;
Tutaj muszę się na chwilę zatrzymać i zejść z tematu "merytorycznego". Postaram się opisać PROWADZENIE sesji. Takiej żywiołowości, takiego zaangażowania nie widziałem nigdzie indziej podczas całego MTS. Większa część prezentacji to filmiki z kodem, a Bartek stojąc tyłem do ekranu opowiadał co się tam właśnie dzieje. Synchronizacja IDEALNA - można by pomyśleć że to leci nagrany wcześniej lektor. Mało tego! Na sali znajdowały się dwa ekrany - jeden wielki i jeden mniejszy. W co prezenter zamienił ten mniejszy (2metrowy?) ekran? Uwaga - w mega-wielkiego IPHONA:). Slajdy pojawiały się jak na wyświetlaczu, po 9 za każdym razem. Kamerka zamontowana nad ekranem śledziła ruchy specjalnego mazaka, którego prelegent używał do dotykowego sterowania prezentacją. Ba, w jednym momencie nawet RYSOWAŁ na panelu wyświetlanym z rzutnika! Coś prawdziwie niesamowitego.&lt;br&gt;
Nie mogę powiedzieć, że dużo nowej wiedzy wyniosłem z tej sesji (w końcu nie tak dawno na ZineDay mieliśmy dwie bardzo fajne sesje o AOP). Myślę jednak, że poruszane tematy wciąż są w wielu organizacjach pomijane i ich promocja jest jak najbardziej potrzebna. Szczególnie w TAKI sposób - oglądało się to po prostu przednio. Nie ma sensu się dalej rozpisywać, to po prostu trzeba było zobaczyć.&lt;/p&gt;
&lt;p&gt;&lt;STRONG&gt;Ocena: &lt;FONT color="#ff0000"&gt;9&lt;/FONT&gt;&lt;/STRONG&gt; (za... wszystko?).&lt;/p&gt;
&lt;h2&gt;4. "Wybrane koncepcje architektoniczne - jak organizować rozbudowane systemy Informatyczne (oraz jak ich NIE organizować)" Tomasz Kopacz&lt;/h2&gt;
&lt;p&gt;Co tu dużo gadać, Tomek Kopacz bezpośrednio po Bartku Pampuchu to jak papieros po obiedzie - czego chcieć wiecej?:) O poziom obawiać się nie trzeba, jedyne zmartwienie to czy zmęczony całym dniem umysł pomieści to morze informacji czekające w sali kongresowej?&lt;br&gt;
Zaczęło się od teoretyzowania, które trwało przez większość sesji. Czy to źle? Nie - nie samym kodem żyje dev.&lt;br&gt;
Na początku otrzymaliśmy odpowiedzi na wprowadzające pytania: Kim jest architekt? Po co jest architekt? Jaki jest architekt? Szczerze mówiąc - wyglądało mi to na "pożyczenie" sobie artykułu z jednego z ostatnich "Architecture Journal". Ale mimo przedstawiania tej samej treści - było interesujące.&lt;br&gt;
Pozostałe 80% prezentacji to SOA w każdej postaci - czym JEST Service Oriented Architecture? A czym NIE JEST Service Oriented Architecture? Co zrobić, aby aplikacja stała się "zorientowana na serwisy", a kiedy nie ma to sensu? Zobaczyliśmy też wiążące się z tym niebezpieczeństwa i czyhające pułapki, otrzymaliśmy kilka porad dotyczących decyzji podejmowanych na różnych etapach projektowania usług.&lt;br&gt;
Po zajmujących rozważaniach przyszedł czas na prezentację tego, czego nie może zabraknąć gdy gdziekolwiek pojawia się słowo "komunikacja", czyli WCF. Jeden sekundowy slajd pokazujący co to jest, a potem już sam miód. Zobaczyliśmy największe zalety WCF, najczęściej stosowane bindingi, nie ominęło nas też wiele innych ciekawostek. Najbardziej zapadła mi w pamięć możliwość odpalenia serwera i klienta WCF w jednym procesie, co daje nam swoiste profilowanie aplikacji i badanie liczby wywołań oraz czasu trwania metod. Praktycznie zerowym nakładem pracy! Po tym przykładzie prelegent dalej sypał z rękawa nieocenionymi poradami. Między innymi (darmowe) narzędzie &lt;a href="http://www.codeplex.com/servicesengine"&gt;MSE&lt;/a&gt; - ja osobiście nie wiedziałem, że jest takie coś i nie wątpię, że kiedyś mi się przyda.&lt;br&gt;
Bardzo polecam ściągnięcie sobie tej prezentacji z internetu i zgłębianie zawartych tam słów kluczowych we własnym zakresie.&lt;br&gt;
Jak widać - dzień pierwszy zakończył się o niebo lepiej niż się rozpoczął.&lt;/p&gt;
&lt;p&gt;&lt;STRONG&gt;Ocena: &lt;FONT color="#ff0000"&gt;8&lt;/FONT&gt;&lt;/STRONG&gt;.&lt;/p&gt;
&lt;hr class="half" /&gt;
&lt;h2&gt;5. "Bezpieczeństwo serwisów WWW – praktyczne uwagi o implementacji zaleceń DBTI ABW w ASP.NET" Zbigniew Łapiński&lt;/h2&gt;
&lt;p&gt;Początek dnia drugiego to dość mocno wyczekiwana prelekcja o bezpieczeństwie. Kto bowiem powie na ten temat więcej, niż megaboss z Agencji Bezpieczeństwa Wewnętrznego? Hmm...&lt;br&gt;
Nie za wiele mogę napisać o tym wystąpieniu. Ja widzę je jak skondensowany semestr ze studiów traktujący o zagrożeniach czyhających na projekt informatyczny. Z ASP.NET niewiele to miało wspólnego. Bardziej - powtórka z zarządzania ryzykiem, podziałem zagrożeń... Nie do końca po to tam przyszliśmy. To, że hasła zapisywane na kartkach przyklejanych do monitorów są fe wiemy od dawna.&lt;br&gt;
Mimo wszystko można było tego posłuchać i usystematyzować posiadaną wiedzę bądź posiąść trochę nowej.&lt;/p&gt;
&lt;p&gt;&lt;STRONG&gt;Ocena: &lt;FONT color="#ff0000"&gt;5&lt;/FONT&gt;&lt;/STRONG&gt; (gdyby temat sesji był inny, ocena byłaby wyższa, ale wtedy pewnie bym tam nie poszedł...).&lt;/p&gt;
&lt;h2&gt;6. Organizacja dostępu do danych w aplikacjach WWW" Tomasz Kopacz&lt;/h2&gt;
&lt;p&gt;Odwiedzanie tego samego prelegenta dwukrotnie podczas jednej konferencji może wydawać się dziwne. Z drugiej strony - po co ryzykować wpadkę, skoro można pójść na pewniaka? Czasy bukmacherskiego uzależnienia mam już za sobą, więc zdecydowałem jak zdecydowałem.&lt;br&gt;
Baaardzo ciężko byłoby choćby pobieżnie opisać wszystkie poruszone na tej sesji zagadnienia. A że pora już nie taka jak być powinna i liczba stron staje się powoli irracjonalnie ogromna, ograniczę się do wymienienia technologii które mogliśmy sobie powąchać: "czyste" ADO.NET (w tym MARS i asynchroniczne połączenia), LINQ (To Sql i To Entities), asynchroniczne strony ASP.NET (na dwa sposoby), WCF, ASMX, DataSety, AJAX, XML, JSON, Script Framework, RSS, ServiceBroker, HierarchyId (Sql Server 2008), FileStream (Sql Server 2008), Enterprise Library (DAAB, Caching, PIAB), Velocity, Astoria. Doprawdy - INSANE! To nie człowiek, to cyborg! TYLE zagadnień w niecałe półtorej godziny i KAŻDE w zrozumiały sposób wyjaśnione. Coś niesamowitego i szalonego. Można było dostać zawrotu głowy, ale - mimo wielkiej chęci przyczepienia się do czegokolwiek - nie da się narzekać że materiału było za dużo. Nic nie zostało bez wyjaśnienia. Oczywiście nie da się tak ogromnej liczby różnych technologii omówić w sposób  bardzo wyczerpujący, ale nie takie było założenie sesji. Wyszliśmy z sali wiedząc co mamy do swojej dyspozycji, a nic nie powstrzymuje nas przed ściągnięciem prezentacji ze stron MTS i "osobistym" badaniom tego co oczom naszym ukazane zostało. Ba, czy ktokolwiek się temu oprze?&lt;br&gt;
I jeszcze jedna krótka uwaga: wreszcie usłyszałem, jak ktoś głośno i wyraźnie mówi: do czego nadaje się Dataset w kontekście programowania WWW? Do NICZEGO!&lt;/p&gt;
&lt;p&gt;&lt;STRONG&gt;Ocena: &lt;FONT color="#ff0000"&gt;9&lt;/FONT&gt;&lt;/STRONG&gt; (za prezentację, na którą ktokolwiek inny potrzebowałby całego dnia a i tak tylko by w głowach namieszał).&lt;/p&gt;
&lt;h2&gt;7. "Programowanie mobilne" Bartłomiej Zass&lt;/h2&gt;
&lt;p&gt;Tutaj wylądowałem niechcący - programowanie mobilne średnio mnie kręci i zapisany byłem na inną sesję. Poszedłem jednak za towarzystwem żeby zobaczyć co tak naprawdę można sobie wyczarować na coraz bardziej popularne urządzenia. Prowadzący na samym początku określił "target audience", i okazało się że jestem dokładnie tam gdzie być powinienem - wpasowałem się jak przysłowiowa dłoń w przysłowiową rękawiczkę.&lt;br&gt;
Większość prezentacji oscylowała wokół koncepcji reagowania naszej aplikacji na przychodzące smsy. Można tak stworzyć program, aby URUCHAMIAŁ się na przyjście smsa o danej treści, WOW! Mało tego, można z zarządzanego kodu zadzwonić sobie gdzieś w odpowiedzi na takie zdarzenie! Cel prezentacji osiągnięty - wszyscy już wiemy jak bardzo CompactFramework poszło do przodu. Jednak nie tylko to! Postęp emulatorów urządzeń mobilnych także musi robić niezłe wrażenie. Emulatory potrafiące dzwonić? To nie czary, widziałem na własne oczy. Forma prezentacji była... ryzykowna. Bardzo interakcyjna i zabawna, ale ryzykowna. Za to ryzyko wielki plus dla Bartka, który po raz kolejny pokazał, że na scenie czuje się jak ryba w wodzie. Na czym to polegało? Można było wysłać smsa pod podany numer, a prezentowana na ekranie aplikacja odpowiednio na niego reagowała. Jednak gdy tekst wysłanej wiadomości nie odpowiadał założeniom programu, był po prostu wyświetlany. Różne przygody z tym związane kilkakrotnie wywoływały salwy śmiechu. Mogło się skończyć różnie, ale wyszło git:).&lt;/p&gt;
&lt;p&gt;&lt;STRONG&gt;Ocena: &lt;FONT color="#ff0000"&gt;7&lt;/FONT&gt;&lt;/STRONG&gt; (tak dużo, bo sesja bardzo fajna, a tak mało, bo nie znoszę programowania mobilnego).&lt;/p&gt;
&lt;h2&gt;8. "Architektura i wykorzystanie usług oprogramowania w chmurze" Grzegorz Gogołowicz&lt;/h2&gt;
&lt;p&gt;Dosłownie kilka słów: usiadłem, zobaczyłem że pan z Redmond przyjechał zareklamować Sql Server i pobawić się w marketingowca czytającego slajdy, i po paru minutach wyszedłem. Potem dowiedziałem się że pojawiły się dema i generalnie było OK. Nie będąc na całości i słysząc umiarkowanie pozytywną opinię, sprzeczną z moją - wstrzymuję się od oceny i żałuję że nie dotrzymałem do końca. Stąd:&lt;/p&gt;
&lt;p&gt;&lt;STRONG&gt;ocena: &lt;FONT color="#ff0000"&gt;X&lt;/FONT&gt;&lt;/STRONG&gt; (bo widziałem tylko pierwsze 15-20 minut).&lt;/p&gt;

&lt;h2&gt;Inne&lt;/h2&gt;
&lt;p&gt;Nie obyło się bez wymiany opinii z innymi uczestnikami i oto plusy/minusy innych sesji oczami moich rozmówców - w wielkim skrócie:
&lt;ul&gt;
&lt;li&gt;"Piękno C# - yield, generics, var i inne dziwne elementy składni C#" Bartłomiej Zass - zgodna z tematem zawartość prezentacji oraz bardzo profesjonalny sposób prowadzenia sesji i interakcji z publicznością, &lt;strong&gt;plus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Metody i sposoby testowania oprogramowania" Piotr Ślężak - jak to ujął znajomy "wreszcie zobaczyłem jak się to powinno robić", co chyba można uznać za spełniony cel prezentacji:), &lt;strong&gt;plus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Wybrane elementy innowacji w Microsoft i Microsoft Research" Mariusz Jarzębowski, Patryk Góralowski - podobno bardzo ciekawe nowe rozwiązania zaprezentowane w fajny sposób, &lt;strong&gt;plus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Efektywne zarządzanie ryzykiem bez/z Team Foundation Server 2008" Tadeusz Golonka - nazwisko mówi samo za siebie, a do tego podobno sesja na zwykłym dla prelegenta, bardzo wysokim poziomie, &lt;strong&gt;plus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Praktyka Silverlight" Tomasz Rakoczy - sesja na MTS kończąca się po 20 minutach? filmik z aplikacji działającej publicznie w necie i do domu? dzień dobry/play/stop/do widzenia? no bez jaj... &lt;strong&gt;MINUS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Integrating Windows Presentation Foundation and Windows Communication Foundation into Your Office Business Applications" Tim Huckaby - po rekomendacji jaką usłyszałem z pewnością zapoznam się z prezentacja i z niecierpliwością czekam na webcast, &lt;strong&gt;plus&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;"Monitorowanie aktywności na SQL Server 2008" Paweł Potasiński, Marek Adamczuk - dla mnie czarna magia, ale znajomy był i powiedział że "chłopaki dali radę", &lt;strong&gt;plus&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;h2&gt;Speaker Idol&lt;/h2&gt;
&lt;p&gt;Dodatkiem do profesjonalnych sesji był konkurs Speaker Idol - "amatorzy" mogli wysłać swoje prezentacje i przekonać sędziów, że nadają się na prelegentów. Półfinał odbył się pierwszego dnia na korytarzu, słychać było niewiele, żarcie zdominowało tą przerwę. Wrażenia zatem co najwyżej średnie. Finał zamykał natomiast całą konferencję następnego dnia. Cztery najlepsze prace były prezentowane na Sali Kongresowej. Taki początek "prelegenckiej" kariery to jest coś! Poziom 5-minutowych wystąpień oceniam naprawdę wysoko, z pewnością _każde_ z nich było lepsze niż _któraś_ sesja "PRO". A że zwycięstwo i główna nagroda - zapewnione miejsce wśród przyszłorocznych prelegentów - trafiło (w pełni zasłużenie, a jak dla mnie II miejsce to Bartek Szafko) w rency mego ziomka JJałbrzykowskiego, tym lepiej. Gratuluję - za rok w relacji nie zostawię na tobie suchej nitki, więc BEWARE ;).&lt;/p&gt;
&lt;h2&gt;Podsumowanie&lt;/h2&gt;
&lt;p&gt;Wiem, że użyłem momentami dość mocnych i bezpośrednich słów, bez owijania w bawełnę. Mam spore doświadczenie w "byciu krytykowanym" i jak najrzadziej staram się krytykować innych. Ale... hola hola! MTS nie jest za darmo! To nie HHH czy C2C, gdzie jedyny koszt poniesiony przez uczestników to trochę swojego czasu. Przygotowanie prezentacji to jest kwestia odpowiedzialności WYŁĄCZNIE prelegenta, nie ma na kogo zwalić winy. Wybierając się tam w roli wykładowcy TRZEBA było sobie zdawać sprawę, że to jedyna konferencja w Polsce o takim rozmachu i renomie. I że - najzwyczajniej w świecie - trzeba wstydu nie mieć, żeby odwalić tam chałę, ponieważ wygórowane oczekiwania uczestników są jak najbardziej uzasadnione. Poza tym wszyscy prosili o oceny, więc oto one.&lt;/p&gt;
&lt;p&gt;Jak zatem zapamiętam MTS w wydaniu 2008?
Z jednej strony - na pewno pewien niedosyt pozostał. Nie chodzi o organizację samej imprezy, chociaż tu na pewno w przyszłym roku znajdzie się pole do poprawy. Może warto wprowadzić dokładniejszą analizę przygotowanych sesji? Weryfikować ich zgodność z deklarowanym tematem i poziomem ZANIM znajdą się na scenie?
Z drugiej strony... Obejrzenie prezentacji wartych obejrzenia, spotkanie ludzi którch się na co dzień nie widuje, klimat wielkiej imprezy - tego nic nie zepsuje. Czy zatem warto było poświęcić dwa dni życia na wycieczki do PKiN? Zdecydowanie tak, choć mogło być lepiej.&lt;br /&gt;Moja subiektywna i uzasadniona powyższymi wypocinami &lt;STRONG&gt;ocena całej konferencji: &lt;FONT color="#ff0000"&gt;7&lt;/FONT&gt;&lt;/STRONG&gt;.&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=2137" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/wra_7C01_enia/default.aspx">wrażenia</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/relacje/default.aspx">relacje</category></item><item><title>Autoryzacja w Web Client Software Factory z wykorzystaniem wyrażeń regularnych</title><link>http://zine.net.pl/blogs/procent/archive/2008/10/04/autoryzacja-w-web-client-software-factory-z-wykorzystaniem-wyra-e-regularnych.aspx</link><pubDate>Sat, 04 Oct 2008 12:27:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:2100</guid><dc:creator>Procent</dc:creator><slash:comments>0</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/2100.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=2100</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=2100</wfw:comment><description>&lt;p&gt;Korzystając z Web Client Software Factory mamy możliwość zdefiniowania reguł bezpieczeństwa, które kontrolują dostęp użytkowników do zasobów. Uzytkownik należy do ról, role mają (bądź nie) uprawnienia wykonywania reguł, natomiast reguły przypisane są do konkretnych adresów URL. Proste. Przykładowy wpis w web.config (z modułu Customers w Order Management Reference Implementation) wygląda tak:&lt;/p&gt;
&lt;pre&gt;&amp;lt;authorization&amp;gt;
  &amp;lt;rule Url=&amp;quot;~/Customers/Default.aspx&amp;quot; Rule=&amp;quot;AllowSearchCustomers&amp;quot; /&amp;gt;
  &amp;lt;rule Url=&amp;quot;~/Customers/SearchCustomers.aspx&amp;quot; Rule=&amp;quot;AllowSearchCustomers&amp;quot; /&amp;gt;
  &amp;lt;rule Url=&amp;quot;~/Customers/CustomerAutoCompleteService.asmx/GetCustomersName&amp;quot; Rule=&amp;quot;AllowAutocomplete&amp;quot; /&amp;gt;
&amp;lt;/authorization&amp;gt;&lt;/pre&gt;
&lt;p&gt;Co w przypadku, gdybyśmy chcieli jakikolwiek dostęp do wszystkich stron w module Customers ograniczyć do ról posiadających prawa do wykonania reguły &amp;quot;AllowUseCustomers&amp;quot;? Prawdopodobnie należałoby w podobny sposób wylistować wszystkie strony z owego modułu... Ohyda.&lt;/p&gt;
&lt;p&gt;Na szczęście architekturę WCSF, podobnie jak wszystkiego ze stajni zespołu Patterns &amp; Practices, przemyślano tak, aby można było właściwie w każde newralgiczne miejsce wprząc własną logikę. Zobaczmy zatem jak poradzić sobie z powyższym problemem. Efekt, który chcemy uzyskać, to plik konfiguracyjny posiadający sekcję &lt;em&gt;authorization&lt;/em&gt; wyglądającą następująco:&lt;/p&gt;
&lt;pre&gt;&amp;lt;authorization&amp;gt;
  &amp;lt;rule Url=&amp;quot;~/Customers/.*&amp;quot; Rule=&amp;quot;AllowUseCustomers&amp;quot; /&amp;gt;
&amp;lt;/authorization&amp;gt;&lt;/pre&gt;
&lt;hr class="half" /&gt;
&lt;p&gt;Na początek trzeba znaleźć kod odpowiedzialny za autoryzację. Po kilkunastowym flircie z Reflectorem wszystko staje się jasne: tą częścią systemu zajmuje się implementacja interfejsu &lt;em&gt;Microsoft.Practices.CompositeWeb.Interfaces.IAuthorizationRulesService&lt;/em&gt;. Napiszmy w takim razie własną:&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;class&lt;/span&gt; RegexAuthorizationRulesService : IAuthorizationRulesService
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	&lt;span class="csComment"&gt;// each url can have multiplerules assigned&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	Dictionary&amp;lt;&lt;span class="csKeyword"&gt;string&lt;/span&gt;, List&amp;lt;&lt;span class="csKeyword"&gt;string&lt;/span&gt;&amp;gt;&amp;gt; _rules = &lt;span class="csKeyword"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="csKeyword"&gt;string&lt;/span&gt;, List&amp;lt;&lt;span class="csKeyword"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;();
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  	&lt;span class="csDocumentation"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  	&lt;span class="csDocumentation"&gt;/// Assigns a new rule name for a given regex-based url.&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  	&lt;span class="csDocumentation"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;void&lt;/span&gt; RegisterAuthorizationRule(&lt;span class="csKeyword"&gt;string&lt;/span&gt; urlPath, &lt;span class="csKeyword"&gt;string&lt;/span&gt; rule)
&lt;span class="csLineNumber"&gt; 10:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt; 11:&lt;/span&gt;  		&lt;span class="csComment"&gt;// create a new list of rules if a given url has not yet been been registered&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 12:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;if&lt;/span&gt; (_rules.ContainsKey(urlPath) == &lt;span class="csKeyword"&gt;false&lt;/span&gt;)
&lt;span class="csLineNumber"&gt; 13:&lt;/span&gt;  			_rules.Add(urlPath, &lt;span class="csKeyword"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="csKeyword"&gt;string&lt;/span&gt;&amp;gt;());
&lt;span class="csLineNumber"&gt; 14:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 15:&lt;/span&gt;  		_rules[urlPath].Add(rule);
&lt;span class="csLineNumber"&gt; 16:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt; 17:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 18:&lt;/span&gt;  	&lt;span class="csDocumentation"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 19:&lt;/span&gt;  	&lt;span class="csDocumentation"&gt;/// Retrieves all rules that were assigned to regexes that match a given url path.&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 20:&lt;/span&gt;  	&lt;span class="csDocumentation"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 21:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;string&lt;/span&gt;[] GetAuthorizationRules(&lt;span class="csKeyword"&gt;string&lt;/span&gt; urlPath)
&lt;span class="csLineNumber"&gt; 22:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt; 23:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;var&lt;/span&gt; rulesList = &lt;span class="csKeyword"&gt;from&lt;/span&gt; entry &lt;span class="csKeyword"&gt;in&lt;/span&gt; _rules
&lt;span class="csLineNumber"&gt; 24:&lt;/span&gt;  						&lt;span class="csKeyword"&gt;where&lt;/span&gt; Regex.IsMatch(urlPath, entry.Key, RegexOptions.IgnoreCase)
&lt;span class="csLineNumber"&gt; 25:&lt;/span&gt;  						&lt;span class="csKeyword"&gt;select&lt;/span&gt; entry.Value;
&lt;span class="csLineNumber"&gt; 26:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 27:&lt;/span&gt;  		&lt;span class="csComment"&gt;// &amp;quot;flatten&amp;quot; the enumerable of List&amp;lt;string&amp;gt; to a one-dimensional array of strings&lt;/span&gt;
&lt;span class="csLineNumber"&gt; 28:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;var&lt;/span&gt; allRules = rulesList.SelectMany(list =&amp;gt; list)
&lt;span class="csLineNumber"&gt; 29:&lt;/span&gt;  			.ToArray();
&lt;span class="csLineNumber"&gt; 30:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt; 31:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;return&lt;/span&gt; allRules;
&lt;span class="csLineNumber"&gt; 32:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt; 33:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt; 34:&lt;/span&gt;  
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ślicznie - mamy już komponent gotowy do "wstrzyknięcia". Tylko gdzie? Po kolejnych kilku minutach analizy WCSF znamy odpowiedź: standardowo wykorzystywana jest &lt;em&gt;Microsoft.Practices.CompositeWeb.Authorization.AuthorizationRulesService
&lt;/em&gt;. Fabryka rejestruje ją podczas startu aplikacji w  swojej klasie &lt;em&gt;Microsoft.Practices.CompositeWeb.WebClientApplication
&lt;/em&gt;. A dokładniej: w metodzie &lt;em&gt;AddRequiredServices&lt;/em&gt; wywoływanej z &lt;em&gt;Application_Start&lt;/em&gt;. Musimy zmienić to zachowanie. Najprościej będzie odziedziczyć z klasy aplikacji i nadpisać standardową metodę, co wygląda tak:&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;class&lt;/span&gt; CustomWebApplication : WebClientApplication
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;protected&lt;/span&gt; &lt;span class="csKeyword"&gt;override&lt;/span&gt; &lt;span class="csKeyword"&gt;void&lt;/span&gt; AddRequiredServices()
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;this&lt;/span&gt;.RootContainer.Services.AddNew&amp;lt;RegexAuthorizationRulesService, IAuthorizationRulesService&amp;gt;();
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;base&lt;/span&gt;.AddRequiredServices();
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Tym sposobem zarejestrujemy własny serwis przed rejestracją swoich usług przez WCSF - i dokładnie o to nam chodzi.&lt;/p&gt;
&lt;p&gt;Na koniec zostało jedynie poinstruowanie systemu, że od teraz należy wykorzystywać właśnie stworzoną klasę aplikacji. W tym celu otwieramy plik &lt;em&gt;Global.asax&lt;/em&gt; i podmieniamy wymienioną tam klasę na własną:&lt;/p&gt;
&lt;pre&gt;&amp;lt;%@ Application Language=&amp;quot;C#&amp;quot; Inherits=&amp;quot;CustomNamespace.CustomWebApplication, CustomAssembly&amp;quot; %&amp;gt;&lt;/pre&gt;
&lt;p&gt;I to by było na tyle - od teraz możemy dowolnie przypisywać reguły adresom URL przy pomocy wyrażeń regularnych.&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=2100" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/.net/default.aspx">.net</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/tools/default.aspx">tools</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/sample/default.aspx">sample</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/wcsf/default.aspx">wcsf</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/entlib/default.aspx">entlib</category></item><item><title>FullHD na VPC przez RDP</title><link>http://zine.net.pl/blogs/procent/archive/2008/09/28/fullhd-na-vpc-przez-rdp.aspx</link><pubDate>Sun, 28 Sep 2008 09:54:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:2078</guid><dc:creator>Procent</dc:creator><slash:comments>4</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/2078.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=2078</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=2078</wfw:comment><description>&lt;p&gt;Co robi programista po powrocie z pracy? Powszechnie wiadomo - siada do pracy. O ile na warunki w miejscu zatrudnienia czasami ma się wpływ minimalny, o tyle domowe środowisko to zupełnie inna para kaloszy. Ostatnio postanowiłem jeszcze bardziej "uidealnić" swoje programistyczne gniazdo w domowym zaciszu i nabyłem kolejną parę oczu na świat - 24 calowe monstrum &lt;a href="http://www.komputronik.pl/Monitory_LCD/Monitory_w_proporcjach_16_10_panoramiczne_/22_27__rozdzielczosc_1920_x_1200_/Hyundai/24_Hyundai_W241D/pelny,id,48087,s,1/" target="_blank"&gt;Hyundai W241D&lt;/a&gt; (wierność marce, a co:) ). W połączeniu z 19" Benq FP93GP ma mi zapewnić komfort pracy o jakim wcześniej mogłem jedynie pomarzyć. Już widziałem te setki linii kodu w trybie PIVOT, już myślałem jak to ślicznie zorganizuje moją pracę z maszynami wirtualnymi, jednym określeniem: juz witałem się z gąską.&lt;/p&gt;
&lt;p&gt;No i przyszło rozczarowanie: jak się okazało, twórcy Virtual PC nie przewidzieli możliwości pracy w rozdzielczości większej niż 1600x1200. Niby to też bardzo dużo, ale nastawiałem się na full-screen w natywnej rozdzielczosci 1920x1200. Niestety, emulowana karta graficzna w VPC posiada jedynie 8MB pamięci i nie ma możliwości przeskoczenia tej bariery. "There is no f*** way!! Or is there...?"&lt;/p&gt;
&lt;p&gt;Na szczęście są na tym świecie mądrzy ludzie! Potrzeba było kilku minut, aby znaleźć w internecie "workaround". Rozwiązanie: włączamy na wirtualce połączenia RemoteDesktop -&gt; łączymy się za pomocą RDP z systemu gospodarza -&gt; ustawiamy tryb FullScreen i... cieszymy się! Łiii...&lt;/p&gt;
&lt;p&gt;Linki:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rozwiązanie znalezione na: &lt;a href="http://www.aspdeveloper.net/Virtual_PC/rn-739-44736_Virtual_PC_2007___Screen_resolution_workaround.aspx" target="_blank"&gt;Virtual PC 2007 :: Screen resolution workaround&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;wytłumaczenie: &lt;a href="http://blogs.msdn.com/virtual_pc_guy/archive/2005/11/21/494961.aspx" target="_blank"&gt;Virtual PC Guy's WebLog - "Virtual PC and video ram"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;VPC na kilku monitorach! - &lt;a href="http://arcanecode.wordpress.com/2006/12/07/arcane-combinations-multiple-monitors-and-virtualpc/" target="_blank"&gt;Arcane Combinations: Multiple Monitors and VirtualPC"&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;P.S. W celu podłączenia się do VPC do sesji "console" należy użyć polecenia mstsc ze switchem "/console". ALE! Może nie zadziałać. I jeśli nie zadziała to można albo zastanawiać się dlaczego a następnie zapytać jakiegoś guru, albo od razu użyć switcha "/admin". Ja byłem skazany na pierwszą drogę - dzięki, &lt;a href="http://www.stilger.eu/" target="_blank"&gt;Karol&lt;/a&gt; :).&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=2078" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/ciekawostki/default.aspx">ciekawostki</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/wirtualizacja/default.aspx">wirtualizacja</category></item><item><title>Virtualny Tip z Marry Softer</title><link>http://zine.net.pl/blogs/procent/archive/2008/09/09/virtualny-tip-z-marry-softer.aspx</link><pubDate>Tue, 09 Sep 2008 06:16:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:1974</guid><dc:creator>Procent</dc:creator><slash:comments>7</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/1974.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=1974</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=1974</wfw:comment><description>&lt;p&gt;Tym razem nowa konwencja. Prawdopodobnie jedyny taki wyskok. Niezainteresowanych moim wcieleniem się w autorkę Harry'ego Pottera zapraszam do pominięcia literackiego wstępu i przeczytania ostatniej, jedynej "wartościowej technicznie" części. &lt;a&gt;Klik&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Wstęp&lt;/h2&gt;
&lt;p&gt;Był to jeden z tych lekkich, letnich dni w magicznej szkole Softwartu. Leniwie rozpoczynał się piątkowy wieczór.&lt;br /&gt;
"Czas na zmiany! " - pomyślała Marry Softer zdejmując czarodziejski kapelusz i rzucając w kąt sfatygowaną różdżkę. "Ile można bawić się z kolegami w lśniące pałki i tajemnicze sakiewki? W ten weekend zrobię coś pożytecznego."&lt;br /&gt;
Wyczarowanie dziurawego czajnika albo liniejącej łasicy jest niczym w porównaniu ze stworzeniem niezawodnego, poprawnie działającego i ślicznego programu. To był cel Marry - poznać inny, nowy rodzaj magii. Zawsze była ambitna.&lt;br /&gt;
Odrzuciła na bok książki zawierające bezużyteczny bełkot do wykrzykiwania podczas nagich pląsów w dzień sabatu. Siadła przed komputerem, lecz zamiast codziennego rytuału uruchamiania komunikatora Czaru-Maru i odwiedzania stron www.ezotv.pl oraz love.mag, podążyła w zupełnie innym kierunku...&lt;/p&gt;
&lt;h2&gt;Rozdział I&lt;/h2&gt;
&lt;p&gt;Jak każda magicznie naznaczona istota, Marry miała niesamowitą zdolność absorpcji wszelkich informacji. Wirujące gałki oczne poświadczały przetwarzanie, rozumienie i zapamiętywanie instrukcji związanych z zakresem The Magic of Software Development. "To jest autentycznie bardziej pasjonujące niż machanie kawałkiem drewna..." - wysapała bezwiednie, zaśliniona ze skupienia. Odgarnęła z czoła niesforny kosmyk włosów, gładząc przy tym tajemniczą bliznę, której pochodzenia mogła się tylko domyślać. Zdaniem nauczycieli z Softwartu kształt owej blizny nie mógł być przypadkowy. Gdy się bliżej przyjrzeć, można było dostrzec dwa nałożone na siebie krzyże. Złowrogi symbol krwi, bólu i cierpienia. Przypadek?&lt;br /&gt;
Marry oderwała się na chwilę od monitora i popadła w głębokie zamyślenie. "Dwa krzyże... Dlaczego ciągle widzę ten symbol?" Przez strony poświęcone poznawanej właśnie materii nieustannie przewijał się ten tajemniczy znak... Cóż to może znaczyć? Jaką niezgłębioną tajemnicę w sobie skrywa?&lt;br /&gt;
"Dokąd zmierzasz, cudowna dziewczyno? Czego pragniesz? Twoje przenaczenie czeka..." - niezidentyfikowany szept wyrwał ją z zadumy. Wystraszona wyłączyła komputer i postanowiła pozwolić umysłowi przyswoić nową wiedzę podczas snu.&lt;br /&gt;
Nie spała jednak spokojnie. Przez całą noc męczyły ją dziwne zjawy, jedne przynoszące przerażenie i ból, inne przygotowujące na ekstazę i uniesienie. Miały jedną wspólną cechę - w tle wszystkimi zmysłami dało się zawsze wyczuć ten niepokojący znak. #.&lt;/p&gt;
&lt;h2&gt;Rozdział II&lt;/h2&gt;
&lt;p&gt;Następnego ranka Marry obudziła się z nowym zapałem. Bez chwili zwłoki zaczęła odkrywać coraz to nowe zakamarki tajników programowania. W swej podróży natknęła się na cykl publikacji o praktyce niesamowicie wspomagającej tą piękną czynność. Po pochłonięciu całej zawartości &lt;a href="http://wss.pl/ArticlesList/63/1.aspx" target="_blank"&gt;"Wstępu do wirtualizacji"&lt;/a&gt; poczuła, że jest gotowa na zmierzenie się z prawdziwym wyzwaniem. Samo określenie "wirtualny" wydało jej się kuszące. Bez chwili zwłoki zabrała się do roboty i już po południu miała środowisko gotowe do przyjęcia całej nowej wiedzy i nieposkromionego zapału TWORZENIA. Rzuciła się na klawiaturę niczym wygłodniała gazela. I pisała, pisała...&lt;/p&gt;
&lt;h2&gt;Rozdział III&lt;/h2&gt;
&lt;p&gt;Blady świt zastał Marry śpiącą z głową opartą o biurko. Migoczący ekran musiał sam przejść w tryb oszczędzania energii. Jedyne co na nim widniało to znany już dobrze, pływający symbol #.&lt;br /&gt;
Marry otworzyła głaskane promieniami porannego słońca oczy. Uniosła głowę, zerknęła na monitor, i uśmiechnęła się do znaku. Przeciągnęła się, wstała i podeszła do lustra. Spojrzała na bliznę i pogładziła ją czule. "Już wiem co oznaczasz... świat wcale nie potrzebuje kolejnej wiedźmy" - wyszeptała. - "Nie zawiodę go..."&lt;br /&gt;
Z fascynacją i świeżymi siłami wróciła do komputera. Jeszcze cały dzień wolnego, cały dzień na programowanie, projektowanie, rozwiązywanie problemów i obchodzenie przeszkód!&lt;br /&gt;
W pokoju rozległo się miarowe stukanie klawiszy. Nic nie mogło jej przeszkodzić. Nic nie mogło zmniejszyć dziewczęcej determinacji do osiągnięcia wymarzonego celu.&lt;/p&gt;
&lt;h2&gt;Rozdział IV&lt;/h2&gt;
&lt;p&gt;Niedzielny wieczór nadszedł niepostrzeżenie. "To już cały dzień? Tak szybko?" Marry zrobiło się żal, jednak była z siebie dumna. Skończone! W ciągu zaledwie jednego weekendu nauczyła się więcej, niż przez cały miesiąc w Softwarcie. A efekt przerósł jej najśmielsze oczekiwania. Była świadoma, że przed nią nieskończone morze nauki, jednak... O dziwo, nie mogła się doczekać systematycznego posiadania nowej wiedzy. Było to dla niej nowe uczucie. Zwykle wyłącznie perspektywa wieczornych szaleństw pozwalała jej zmobilizować się do pracy. Było to nowe i... podobało jej się!&lt;br /&gt;
Z satysfakcją zapisała na wirtualnym dysku wszystkie zmiany. Zmniejszyła ekran, wcisnęła krzyżyk wyłączający system gościa. Wirtualna maszyna zapytała o sposób wyłączenia, a Marry bez wahania wybrała z listy Save State. Zapis stanu się rozpoczął...&lt;/p&gt;
&lt;h2&gt;Rozdział V&lt;/h2&gt;
&lt;p&gt;Wszystko stało się tak szybko... Trwało zaledwie kilka sekund, a mimo to w umyśle Marry chwile te zostaną na zawsze wyryte niczym niekończące się godziny. Proces zapisu stanu maszyny zawierającej całą jej piękną pracę doszedł do 3%, gdy drzwi z hukiem wpadły do środka. W przejściu stanęła mroczna postać. "HA!" - zakrzyknęła złowrogo - "mam cię, M.S.! Jam jest Lord GoogleMort! Przez lata próbowałem do ciebie dotrzeć, zniszczyć cię, zmiażdżyć!" Marry w ułamku sekundy przypomniała sobie wszystkie straszne opowieści, które z takim trudem wyparła ze świadomości. Powróciły wspomnienia z dzieciństwa, niewyjaśniona śmierć rodziców, strach przed jutrem, niepewność nadchodzących lat... To, z czym jej umysł uporał się z tak wielkim trudem, stało przed nią... Twarz nieznajomego wykrzywiła się okrutnie. "Pracowałem nad nowym zaklęciem, któremu na pewno się nie oprzesz! Już nigdy mnie nie poniżysz, nigdy ze mną nie zwyciężysz!" Uniosł nad głowę czarną różdżkę. Wydobywające się z niej ciemne iskry spadały na podłogę wydając przerażający syk, przynoszący na myśl najgłębsze otchłanie rozpaczy.&lt;br /&gt;
Marry oniemiała. Jej rozbiegany wzrok szukał ratunku, jednak jedyna możliwa broń była za daleko. Rzucona niedbale różdżka potoczyła się pod łóżko i leżała tam przez ostatnie dni. Wzrok zatrzymał się na chwilę na monitorze. Pasek zapisu maszyny wirtualnej sięgał 90%. "Akurat teraz, gdy moje życie zaczęło nabierać sensu..." pomyślała i w jej oku po raz pierwszy od lat zalśniła łza. Bezradnie zdała się na łaskę losu.&lt;br /&gt;
Lord GoogleMort zakończył wykonywać sekwencję ruchów wywołujących nowe, przerażające zaklęcie. Wycelował różdżkę w Marry, otworzył usta. Napięcie w pokoju sięgnęło zenitu. Oboje wiedzieli, że słowo rozpoczynające właśnie drogę przez przeponę Lorda oznacza koniec. Nieodwracalny koniec.&lt;br /&gt;
"CHROOOOME !!!" - echo niosło się daleko, daleko... W pomieszczeniu zapanowała smolista ciemność.&lt;/p&gt;
&lt;h2&gt;Rozdział VI&lt;/h2&gt;
&lt;p&gt;Marry wstała z podłogi. Stopniowo odzyskiwała wzrok. Po chwili mogła rozpoznać kształt wyrwanych drzwi, zarys okna przez które wpadały resztki światła niedzielnego wieczora. Gdy szok powoli mijał, do jej świadomości pulsującymi podrygami zaczął płynąć ból. Nie do zniesienia. Uniosła dłoń do czoła, pogładziła bliznę. Krzyknęła i natychmiast cofnęła rękę.&lt;br /&gt;
Marry spojrzała na palce - lepka czerwień nie pozostawiała wątpliwości. To blizna! To ona otrzymała cios straszliwym zaklęciem Chrome! &lt;br /&gt;
Rozejrzała się, jednak po Lordzie GoogleMorcie nie było ani śladu. Wtedy do niej dotarło i natychmiast zapomniała o bólu. Jej dzieło! Jej dziecko! Jej pierwszy program! Zaklęcie było tak silne, że spowodowane przez nie napięcie wyłączyło wszystkie urządzenia. A przeciez zapis stanu maszyny wirtualnej się nie zakończył!&lt;br /&gt;
Włączyła ponownie komputer, z zaciśniętymi wargami spróbowała uruchomić swoje wirtualnie środowisko... Niestety... "The virtual image could not be restored because the saved state was either corrupt or incompatible with this version of Virtual PC."&lt;/p&gt;
&lt;h2&gt;&lt;a name="Epilog"&gt;Epilog&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Zrozpaczona Marry nie mogła uwierzyć. Tyle pracy stracone? Trzy dni na marne?&lt;br /&gt;
Wtedy jej wzrok przykuło coś dziwnego. W katalogu, w którym powinny znajdować się dwa pliki, widniały trzy! VMC - opcje maszyny, VHD - dysk maszyny, to oczywiste. A trzeci? VSV... "Nigdy czegoś takiego nie widziałam... Trudno, gorzej i tak być nie może" - pomyślała i usunęła nieznany twór. Chwila niepewności, dwuklik na VMC... Działa! I wszystkie dane są tam gdzie być powinny!&lt;br /&gt;
Na twarzy Marry zagościł uśmiech. Wszystkiego się już domyśliła. &lt;b&gt;W katalogu maszyny wirtualnej VHD zawiera dane, podczas gdy VSV to tylko aktualny zatrzymany stan fizyczny komputera! Jego usunięcie działa po prostu jak wyciągnięcie wtyczki! Dlatego też jeśli podczas zapisywania stanu maszyny stanie się coś niedobrego, to pozbycie się go może być rozwiązaniem!&lt;/b&gt;&lt;br /&gt;
Ufff... odetchnęła z ulgą. "Teraz mogę zacząć myśleć o Lordzie GoogleMorcie..."&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=1974" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/marry+softer/default.aspx">marry softer</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/wirtualizacja/default.aspx">wirtualizacja</category></item><item><title>Relacja z ZineDay 2008</title><link>http://zine.net.pl/blogs/procent/archive/2008/09/08/relacja-z-zineday-2008.aspx</link><pubDate>Mon, 08 Sep 2008 09:47:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:1959</guid><dc:creator>Procent</dc:creator><slash:comments>0</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/1959.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=1959</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=1959</wfw:comment><description>&lt;p&gt;O ZineDay słychać było już od jakiegoś czasu. Założyciel &lt;a href="http://www.zine.net.pl"&gt;Zine'a&lt;/a&gt;, &lt;a href="http://zine.net.pl/blogs/mgrzeg/"&gt;Michał Grzegorzewski&lt;/a&gt;, zorganizował (pewnie przy pomocy wielu osób) konferencję dla twórców, bloggerów i czytelników tego portalu. Wszystko odbyło się 6 września 2008 w siedzibie Microsoft w Warszawie.&lt;/p&gt;
&lt;p&gt;Spotkanie nie miało rangi DevDays, HHH, C2C czy MTS. Ot, zlot kilkudziesięciu osób połączonych jednym portalem, bez wielkich akcji marketingowych i zaplecza "logistycznego". Jednak zarówno na organizację, jak i przebieg oraz menu prezentacyjne raczej nikt nie mógł narzekać. Liczba osób także nie była mała - około 50.&lt;br /&gt;
Cały dzień podzielony został na dwie części: "konferencyjne" prezentacje oraz &lt;u&gt;konkurs&lt;/u&gt;. One by one:&lt;/p&gt;
&lt;h2&gt;Gael Fraiteur - "Addressing non-functional requirements with aspects"&lt;/h2&gt;
&lt;p&gt;Jako pierwszy wystąpił autor &lt;a href="http://www.postsharp.org/"&gt;PostSharpa&lt;/a&gt; - darmowej biblioteki "przynoszącej Aspect-Oriented Programming do .NET". Sesja ta jednak wbrew pozorom wcale nie miała na celu zareklamowania produktu Gaela. Zamiast tego zostaliśmy zaproszeni na wycieczkę po świecie aspektów - co to jest, po co zostały wymyślone, jakie korzyści płyną z ich zastosowania, kiedy i dlaczego należy się tym zainteresować. Odpowiedzi? Zainteresować się należy JAK NAJSZYBCIEJ. Dlaczego? Odsyłam do wujka Google (lub materiału wideo który ma się ukazać na Zine), ponieważ temat jest na teraz za długi i za szeroki.&lt;br /&gt;
Tak czy siak, podczas wystąpienia Gael nie ograniczył się do prezentacji jedynie swojego rozwiązania. Wraz z PostSharpem liznęliśmy Policy Injection Application Block z Microsoftowej Enterprise Library, Spring.NET oraz Castle Project. Każdy z przedstawionych frameworków został pobieżnie omówiony i zaprezentowany w praktyce. Jakie są różnice w implementacji, jakie mają możliwości, jakie wady i jakie zalety? Było to bardziej odsłonięcie czubka prawdziwej góry lodowej. Myślę, że zarówno programista AOP jak i nowicjusz (do których głównie kierowany był występ) wyniósł z sali nowe informacje.&lt;br /&gt;
Oprócz praktyki wykorzystania gotowych bibliotek dowiedzieliśmy sie też jak one powstają - niektóre modyfikują gotowy kod MSIL (jak Post#), inne korzystają z remotingowych Proxy (PIAB), jeszcze inne tworzą własne klasy pośrednie (Spring i Castle).&lt;/p&gt;
&lt;h2&gt;Andras Belokosztolszki - "Managing change in the database world"&lt;/h2&gt;
&lt;p&gt;Myślałem, że ta sesja będzie nudną przerwą w tym aspektowym dniu. Na szczęście - jakże się myliłem! Prowadzący z firmy RedGate znakomitą angielszczyzną omówił kluczowe zagadnienia w wersjonowaniu baz danych. Przedstawił problemy wynikające z modyfikacji baz "w produkcji" (dowiedzieliśmy się np o problemach z zastosowaniem procedury sp_rename mogących przyprawić o zawrót głowy!). Pokazał na żywych przykładach przed jak wielkim wyzwaniem stoją autorzy narzędzi mających ten proces uprościć. Ujawnione zmiany pomiędzy mechanizmami przechowywania metadanych w SQL Server 2000 i 2005 są doprawdy zadziwiające - i wcale nie w pozytywnym tego słowa znaczeniu. Olaboga! Bez fałszywego marketingu, zero ściemy. Wydobywanie metadanych z różnych baz a następnie porównanie ich wbrew pozorom nie ogranicza się do kilku SELECTów - wzbudza szacunek.&lt;br /&gt;
O ile wątpię, czy administratorzy baz danych bądź programiści spędzający większość czasu "po tamtej stronie serwera" dowiedzieli się czegoś nowego, o tyle za dobór tematu sesji na typowy zlot .NETowców należą się brawa.&lt;/p&gt;
&lt;h2&gt;Gael Fraiteur &amp; Jakub Binkowski - "More complex aspects using PostSharp"&lt;/h2&gt;
&lt;p&gt;Programowania aspektowego ciąg dalszy. Tym razem do Gaela dołączył na scenie zine'owy ziomek &lt;a href="http://zine.net.pl/blogs/jakubin/"&gt;JBinkowski&lt;/a&gt;. Celem było zaprezentowanie oraz dokładniejsze omówienie bardziej zaawansowanych możliwości samego PostSharpa. W konwencji Mango Gdynia;) - Kuba jako biedny developer, Gael jako wszechwiedzący "problem-solver". Jednak mimo takiego porównania całość oglądało się bardzo przyjemnie, z pewnością było to bardziej interesujące niż jednoosobowe przedstawienie kilkudziesięciu linijek kodu.&lt;br /&gt;
Rozpoczęto od zaprezentowania banalnej aplikacji "książka kontaktów" oraz problemów jakie mają z nią końcowi użytkownicy (albo "THOSE UNGRATEFUL SHAMELESS BASTARDS THAT DARE TO COMPLAIN!", jak ich bez owijania w bawełnę określił Jakub:) ). Kłopoty najróżniejsze - od wolnej odpowiedzi na akcje użytkownika, przez niewyłapane wyjątki aż po wielowątkowość. Post# lekiem na całe zło:). Najbardziej zaawansowany scenariusz musiał zrobić wrażenie na wszystkich obecnych - Gael zademonstrował domiplementowanie interfejsu INofityPropertyChange do własnych klas poprzez jeden atrybut! Za magię pod owym atrybutem odpowiadało kilka PostSharpowych aspektów, których implementacja, choć bardzo interesująca, była moim zdaniem zbyt skomplikowana do przedstawienia na takim spotkaniu. Za mało czasu, za dużo kodu. Ale z niecierpliwością czekam na udostępnienie slajdów z prezentacji aby własnoocznie zobaczyć co i jak.&lt;/p&gt;
&lt;h2&gt;Konkurs na projekt Open Source&lt;/h2&gt;
&lt;p&gt;Konkurs na projekt Open Source został ogłoszony kilka miesięcy temu na &lt;a href="http://zine.net.pl/blogs/mgrzeg/archive/2008/07/21/1317.aspx"&gt;blogu Michała&lt;/a&gt;. Do "finału" (czyli prezentacji na ZineDay) dotarło 6 projektów. Trzy najlepsze zasłużyły na nagrody główne - roczną subskrypcję MSDN Premium, trzy kolejne - na Vistę. Wszystkie prezentacje trzymały odpowiedni poziom, widać było zaangażowanie i przygotowanie autorów do prezentacji. Nie ma się co dziwić - było o co walczyć. Całość przypominała mi trochę Imagine Cup z tą różnicą, że zamiast stresować się "na scenie" mogłem po prostu oddać swój głos na obradach jury:). Gratulacje dla twórców wszystkich projektów i dzięki za interesujące ich przedstawienie.&lt;/p&gt;
&lt;h2&gt;Podsumowanie&lt;/h2&gt;
&lt;p&gt;Dzień zaliczam do bardzo udanych. Masa informacji o coraz popularniejszym w świecie .NET "paradygmacie" tworzenia oprowamowania + interesujące i bardzo przydatne porady "czego nie robić w SQL Server" + fajne prezentacje zgłoszonych projektów = event, na którym naprawdę warto być! Dzięki i czekamy na następne?&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=1959" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/wra_7C01_enia/default.aspx">wrażenia</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/relacje/default.aspx">relacje</category></item><item><title>Własna implementacja formatowania kodu C# -&gt; HTML</title><link>http://zine.net.pl/blogs/procent/archive/2008/09/02/w-asna-implementacja-formatowania-kodu-c-html.aspx</link><pubDate>Tue, 02 Sep 2008 18:24:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:1887</guid><dc:creator>Procent</dc:creator><slash:comments>4</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/1887.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=1887</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=1887</wfw:comment><description>&lt;H2&gt;ToBeDone&lt;/h2&gt;
&lt;p&gt;Każdy prowadzący technicznego bloga wcześniej czy później napotyka problem: jak przedstawić swój kod na stronie? Do wyboru mamy teoretycznie wiele możliwości. Jest popularny &lt;a href="http://www.manoli.net/csharpformat/" target="_blank"&gt;formatter Manoli&lt;/a&gt;, jest &lt;a href="http://www.actiprosoftware.com/Products/DotNet/ASPNET/CodeHighlighter/pastecode.aspx" target="_blank"&gt;Actipro CodeHighlighter&lt;/a&gt;, o jeszcze innym rozwiązaniu &lt;a href="http://jacekciereszko.pl/2008/08/formatowanie-kodu-w-blogger.html" target="_blank"&gt;pisał ostatnio Jacek Ciereszko&lt;/a&gt;. Gdy jednak rozpoczynalem swoją przygodę z blogowaniem ponad pół roku temu, nie mogłem znaleźć rozwiązania satysfakcjonującego mnie w 100%. Czego oczekiwałem? Pełnej kontroli nad otrzymanym kodem, łatwości dostosowania do własnych potrzeb oraz... możliwości momentalnego wprowadzenia poprawek, gdyby okazało się że coś nie jest tak jak powinno. I tak powstał Procent.Samples.CodeFormatter:). Chwilę po założeniu bloga powstała wersje "pre-alfa"(?) służąca mi aż do niedawna. Ostatnio postanowiłem doprowadzić ją do ładniejszego stanu i zaprezentować tutaj (po zakończeniu tych czynności kod robi więcej niż robił, a jest go 2x mniej! refactoring rulz). Zanim jednak przejdziemy do technicznych rozważań - ONLINE DEMO prezentujące główną funkcjonalność (czyli "paste -&gt; format -&gt; use") znajduje się pod adresem &lt;a href="http://www.maciejaniserowicz.com/samples/CodeFormatter.aspx" target="_blank"&gt;http://www.maciejaniserowicz.com/samples/CodeFormatter.aspx&lt;/a&gt;. CzkItOłt.&lt;/p&gt;
&lt;h2&gt;Rzut oka z lotu ptoka - UML&lt;/h2&gt;
&lt;p&gt;Na początek przedstawienie koncepcji - jak widzę problem od strony "techniczno-obiektowej". Całość procesu to nic innego jak odpowiednie przetwarzanie otrzymanego z zewnątrz tekstu: krok po kroku, reguła po regule. Każdy z tych kroków da się logicznie wyodrębnić i opisać, a co za tym idzie - opakować w osobną klasę. &lt;a href="http://en.wikipedia.org/wiki/Separation_of_concerns" target="_blank"&gt;Separation of concerns&lt;/a&gt;, baby. Kolorowanie słów kluczowych nie powinno teoretycznie mieć wpływu na numerowanie linii, co z kolei ma się nijak do doklejenia notki od autora narzędzia, prawda?&lt;/p&gt;
&lt;p&gt;Takie założenie pozwoliło mi traktować modyfikacje przekazanego tekstu jako łańcuch następujących po sobie czynności. Aż pozwolę sobie podkreślić najważniejsze słowo: &lt;u&gt;łańcuch&lt;/u&gt;. Co za tym idzie - każda pojedyncza modyfikacja to ogniwo tej struktury mająca za zadanie wykonać robotę i przekazać efekt swojej pracy &lt;a href="http://www.amazon.com/Further-Down-Spiral-Nine-Nails/dp/B000001Y89" target="_blank"&gt;dalej&lt;/a&gt;. Tak oto powstała &lt;em&gt;ChainElement&lt;/em&gt;. Banalne - w sam raz na pierwszy na tym blogu diagram klas(y) (sic!)!&lt;/p&gt;
&lt;img src="http://zine.net.pl/photos/posts_pictures/images/1880/original.aspx" /&gt;
&lt;p&gt;Myślimy dalej i wymyślamy: tak naprawdę można rozdzielić wszystkie możliwe czynności na dwie logiczne grupy. Elementy łańcucha z pierwszej z nich operują na tekście jako całości (np. wspomniane doklejenie notki "Generated by..."), a z drugiej grzebią się w zawartości i zdobią odpowiednie fragmenty tekstu kodem CSS (np. "ozdabiacze" słów kluczowych czy komentarzy). O ile nie możemy przewidzieć co mogą robić ogniwa przynależące do pierwszej grupy, o tyle można domniemywać, że cała druga grupa ogranicza się do zdefiniowana odpowiedniego wyrażenia regularnego i tekstu mającego zastąpić wyszukaną wartość. Tak scharakteryzowana funkcjonalność da się zaimplementować w klasie bazowej zawierąjacej całą potrzebną logikę. A więc przedstawiamy &lt;em&gt;CssDecoratingElement&lt;/em&gt; na diagramie numer dwa:&lt;/p&gt;
&lt;img src="http://zine.net.pl/photos/posts_pictures/images/1881/original.aspx" /&gt;
&lt;p&gt;Nowa klasa implementuje abstrakcyjną &lt;em&gt;ProcessString&lt;/em&gt;, ponieważ wie co ma zrobić z otrzymanym tekstem. Właściwość &lt;em&gt;CssClass&lt;/em&gt; pozwala na skonfigurowanie stylu css wykorzystanego przez dany element, a abstrakcyjna właściwość &lt;em&gt;_regexPattern&lt;/em&gt; wymusza na klasach dziedziczących zdefiniowanie kryteriów wyszukiwania napisu do zastąpienia.&lt;br /&gt;
Po takich przemyśleniach przychodzi czas na zdefiniowanie kolejnych stacji, na których musi się zatrzymać czysty tekst aby wyjechać "w chmurę" jako śliczny, kolorowy HTML. Nazwy klas mówią same za siebie, zatem kolejny diagram (ale dziś ze mnie sztywniak) powinien być wystarczający:&lt;/p&gt;
&lt;img src="http://zine.net.pl/photos/posts_pictures/images/1883/original.aspx" /&gt;
&lt;p&gt;Po zaimplementowaniu takiej struktury można pokusić się o dołożenie kilku bonusów. Jeden z nich to możliwość konfiguracji sposobu, w jaki CSS zostaje umieszczony w wynikowym tekście. Na moje potrzeby całkowicie wystarcza generacja atrybutu &lt;em&gt;"class"&lt;/em&gt; z odpowiednią nazwą, resztę i tak mam podefiniowaną w zewnętrznych plikach. Wychodząc do ludzi wypada jednak zaoferować możliwość kolorowania składni "inline", aby otrzymany wynik był gotów do natychmiastowego użycia. Do tego celu utworzyłem minihierarchię "Inline style providers" wraz z dwoma przykładowymi implementacjami. Pierwsza z nich (&lt;em&gt;CSharpStyleProvider&lt;/em&gt;) pobiera na sztywno zdefiniowane style prosto z zasobów aplikacji, a druga (&lt;em&gt;CustomStyleProvider&lt;/em&gt;) poprzez dziedziczenie z Dictionary&amp;lt;string, string&amp;gt; pozwala na własne dowolne definicje:&lt;/p&gt;
&lt;img src="http://zine.net.pl/photos/posts_pictures/images/1884/original.aspx" /&gt;
&lt;p&gt;Zauważmy jedną rzecz: taka architektura sprawiła, że mamy omówione prawie całe zagadnienie, a nigdzie nie pojawiła się jeszcze nazwa CSharpCodeFormatter! Przy przedstawionych założeniach każdy konkretny CodeFormatter to nic innego jak zbiór odpowiednich klocków - wybierz czynności jakie chcesz wykonać, zbuduj z nich łańcuch i voilà!&lt;/p&gt;
&lt;img src="http://zine.net.pl/photos/posts_pictures/images/1882/original.aspx" /&gt;
&lt;p&gt;Dodatkowo wprowadziłem jeszcze jeden podział w zaimplementowanych elementach łańcucha. Większość z nich jest niezależna od składni C#, więc warto było zaznaczyć możliwość ich bezpośredniego wykorzystania przy implementacji kolejnych języków:&lt;/p&gt;
&lt;img src="http://zine.net.pl/photos/posts_pictures/images/1885/original.aspx" /&gt;
&lt;h2&gt;C# diving&lt;/h2&gt;
&lt;p&gt;Po takim zarysowaniu zagadnienia czas na kilka rzutów oczami prosto w najbardziej interesujące miejsca w kodzie.&lt;/p&gt;
&lt;h3&gt;Inicjalizacja łańcucha&lt;/h3&gt;
&lt;p&gt;Krótko: wybieramy elementy, ustawiamy w odpowiedniej kolejności i:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;protected&lt;/span&gt; &lt;span class="csKeyword"&gt;override&lt;/span&gt; &lt;span class="csKeyword"&gt;void&lt;/span&gt; InitializeChain()
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	Chain = &lt;span class="csKeyword"&gt;new&lt;/span&gt; HtmlEncoder();
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	Chain.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; DocumentationFormatter())
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  		.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; SingleLineCommentsFormatter())
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  		.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; MultiLineCommentsFormatter())
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  		.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; DirectivesFormatter())
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  		.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; StringsFormatter())
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  		.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; KeywordsFormatter(_keywords))
&lt;span class="csLineNumber"&gt; 10:&lt;/span&gt;  		.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; LinesCounter())
&lt;span class="csLineNumber"&gt; 11:&lt;/span&gt;  		.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; Wrapper())
&lt;span class="csLineNumber"&gt; 12:&lt;/span&gt;  		.Attach(&lt;span class="csKeyword"&gt;new&lt;/span&gt; CopyrightWriter());
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Inline CSS vs CSS class&lt;/h3&gt;
&lt;p&gt;Decyzję o tym jaki kod generować można podjąć na dwóch poziomach: całego formattera oraz poszczególnych elementów łańcucha. Faktyczne wprowadzenie tej decyzji w życie odbywa się w &lt;em&gt;CssDecoratingElement&lt;/em&gt; i wygląda tak:&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;protected&lt;/span&gt; &lt;span class="csKeyword"&gt;string&lt;/span&gt; GetStyleFragment()
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;if&lt;/span&gt; (InjectInlineCss)
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;return&lt;/span&gt; &lt;span class="csKeyword"&gt;string&lt;/span&gt;.Format(&lt;span class="csString"&gt;&amp;quot;style=\&amp;quot;{0}\&amp;quot;&amp;quot;&lt;/span&gt;, InlineStyleProvider.GetStyle(CssClass));
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;return&lt;/span&gt; &lt;span class="csKeyword"&gt;string&lt;/span&gt;.Format(&lt;span class="csString"&gt;&amp;quot;class=\&amp;quot;{0}\&amp;quot;&amp;quot;&lt;/span&gt;, CssClass);
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  }
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Przed wykorzystaniem elementy muszą zostać odpowiednio skonfigurowane, &lt;em&gt;CSharpFormatter&lt;/em&gt; robi to tak:&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;private&lt;/span&gt; &lt;span class="csKeyword"&gt;void&lt;/span&gt; PrepareChainForStyleInlining()
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;foreach&lt;/span&gt; (&lt;span class="csKeyword"&gt;var&lt;/span&gt; element &lt;span class="csKeyword"&gt;in&lt;/span&gt; Chain.AsEnumerable().OfType&amp;lt;CssDecoratingElement&amp;gt;())
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  		element.InjectInlineCss = &lt;span class="csKeyword"&gt;true&lt;/span&gt;;
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  		element.InlineStyleProvider = &lt;span class="csKeyword"&gt;this&lt;/span&gt;.InlineStyleProvider;
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;ChainElement.AsEnumerable&lt;/h3&gt;
&lt;p&gt;Na strukturach takich jak omawiany łańcuch chce się czasem poszaleć przy użyciu LINQ. Poniższa metoda umożliwia to zwracając wszystkie elementy łańcucha od obecnego w głąb:&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;public&lt;/span&gt; IEnumerable&amp;lt;ChainElement&amp;gt; AsEnumerable()
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;yield&lt;/span&gt; &lt;span class="csKeyword"&gt;return&lt;/span&gt; &lt;span class="csKeyword"&gt;this&lt;/span&gt;;
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;if&lt;/span&gt; (_next == &lt;span class="csKeyword"&gt;null&lt;/span&gt;)
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;yield&lt;/span&gt; &lt;span class="csKeyword"&gt;break&lt;/span&gt;;
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;foreach&lt;/span&gt; (&lt;span class="csKeyword"&gt;var&lt;/span&gt; element &lt;span class="csKeyword"&gt;in&lt;/span&gt; _next.AsEnumerable())
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;yield&lt;/span&gt; &lt;span class="csKeyword"&gt;return&lt;/span&gt; element;
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Embedded resources&lt;/h3&gt;
&lt;p&gt;Domyślne style "inline" oraz słowa kluczowe C# (ściągnięte &lt;a href="http://msdn.microsoft.com/en-us/library/x53a06bb.aspx" target="_blank"&gt;stąd&lt;/a&gt;) zapisane są w plikach tekstowych dołączonych do projektu jako "embedded resource". Dzięki temu podczas pisania aplikacji możemy łatwo edytować ich zawartość, a po kompilacji nic nam nie zaśmieca folderu wynikowego. Oznaczenie pliku jako wewnętrzne zasoby odbywa się w VS następująco:&lt;/p&gt;
&lt;img src="http://zine.net.pl/photos/posts_pictures/images/1886/original.aspx" /&gt;
&lt;p&gt;, natomiast wykorzystanie takiego pliku w kodzie demonstruje poniższy wycinek inicjalizujący kolekcję słów kluczowych w programie:&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;private&lt;/span&gt; &lt;span class="csKeyword"&gt;static&lt;/span&gt; IEnumerable&amp;lt;&lt;span class="csKeyword"&gt;string&lt;/span&gt;&amp;gt; InitializeKeywords()
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;using&lt;/span&gt; (Stream resourceStream = Assembly.GetExecutingAssembly()
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  		.GetManifestResourceStream((&lt;span class="csString"&gt;&amp;quot;Procent.Samples.CodeFormatter.Resources.CSharpKeywords.txt&amp;quot;&lt;/span&gt;)))
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;using&lt;/span&gt; (StreamReader reader = &lt;span class="csKeyword"&gt;new&lt;/span&gt; StreamReader(resourceStream))
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  		{
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  			&lt;span class="csComment"&gt;// reading a stream...
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Najciekawszy Regex&lt;/h3&gt;
&lt;p&gt;Manipulacje tekstem odbywają się przy użyciu wyrażeń regularnych. Nie ma sensu wypisywania tutaj wszystkich, z których skorzystałem, jednak jedno jest warte osobnego przedstawienia. Proces formatowania kodu odbywa się krok po kroku, co oznacza że element formatujący słowa kluczowe otrzyma tekst już częściowo sformatowany, a co za tym idzie - usiany tagami &amp;lt;span&amp;gt;, których nie powinien ruszać. Dodatkowo przyjąłem założenie, że każdy fragment tekstu nie może zostać sformatowany więcej niż raz. Dzięki temu przykładowo "int" będące częścią wcześniej pokolorowanego literału napisowego (bo &lt;em&gt;StringsFormatter&lt;/em&gt; jest dołączony do łancucha przed &lt;em&gt;KeywordsFormatter&lt;/em&gt;) nie zostanie dodatkowo oznaczone klasą słów kluczowych - i dobrze. Za takie sztuczki odpowiedzialne jest raptem kilka znaków pilnujących, aby odnaleziony tekst nie znajdował się wewnątrz taga XML bądź nie był jego częścią. Efekt ten osiągam doklejając je z przodu właściwego wyrażenia odpowiedzialnego za odnalezienie innych fragmentów tekstu. Szczegółowe zapoznanie się i rozgryzienie tego wyrażenia pozostawiam zainteresowanym jako pracę domową:&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;const&lt;/span&gt; &lt;span class="csKeyword"&gt;string&lt;/span&gt; _outsideTagPatternStart = &lt;span class="csString"&gt;&amp;quot;(?&amp;lt;!&amp;lt;.*?(&amp;gt;.*)?)&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h3&gt;Najciekawszy CSS&lt;/h3&gt;
&lt;p&gt;Mistrzem CSS nie jestem, więc zamiast się wymądrzać odeślę do źródła tajemnej wiedzy o odpowiednim zawijaniu linii omijającym luki w poszczególnych przeglądarkach. Nie jestem w 100% pewny czy to zawsze działa, ale mimo to link: &lt;a href="http://myy.helia.fi/~karte/pre-wrap-css3-mozilla-opera-ie.html" target="_blank"&gt;"Making preformated &amp;lt;pre&amp;gt; text wrap in CSS3, Mozilla, Opera and IE"&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Przykładowy element łańcucha&lt;/h3&gt;
&lt;p&gt;I na koniec przykład jednego z "kroków" mielenia tekstu: klasa odpowiedzialna za formatowanie dyrektyw kompilatora (czyli linii w których pierwszym "niebiałym" znakiem jest #):&lt;/p&gt;


&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;class&lt;/span&gt; DirectivesFormatter : CssDecoratingElement
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;protected&lt;/span&gt; &lt;span class="csKeyword"&gt;override&lt;/span&gt; &lt;span class="csKeyword"&gt;string&lt;/span&gt; _defaultCssClass
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  		get { &lt;span class="csKeyword"&gt;return&lt;/span&gt; &lt;span class="csString"&gt;&amp;quot;csDirective&amp;quot;&lt;/span&gt;; }
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;protected&lt;/span&gt; &lt;span class="csKeyword"&gt;override&lt;/span&gt; &lt;span class="csKeyword"&gt;string&lt;/span&gt; _regexPattern
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt; 10:&lt;/span&gt;  		get { &lt;span class="csKeyword"&gt;return&lt;/span&gt; &lt;span class="csString"&gt;@&amp;quot;^\s*#.*\n&amp;quot;&lt;/span&gt;; }
&lt;span class="csLineNumber"&gt; 11:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt; 12:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Proste, łatwe i przyjemne - wszystko mamy wyciągnięte do odpowiednich klas bazowych.&lt;/p&gt;
&lt;hr class="half" /&gt;
&lt;p&gt;To tyle przykładów z kodu. Zachęcam do ściągnięcia źródeł, zapoznania się z nimi "sam na sam" i wyrażenia swojej opinii. Co można zrobić lepiej/inaczej/wydajniej/bardziej interesująco?&lt;/p&gt;
&lt;h2&gt;Samary&lt;/h2&gt;
&lt;p&gt;Mechanizmy .NET wykorzystane w praktyce:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;regular expressions&lt;/li&gt;
&lt;li&gt;embedded resources&lt;/li&gt;
&lt;li&gt;słówko kluczowe yield&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Możliwości rozwoju:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;implementacja kolejnych języków&lt;/li&gt;
&lt;li&gt;implementacja innego zdobienia nieparzystych linii&lt;/li&gt;
&lt;li&gt;więcej możliwości konfiguracyjnych (np. możliwe do wyłączenia dodawanie numerów linii czy konfigurowanie generowanych nazw klas, tak jak teraz możliwe jest definiowanie własnych styli inline)&lt;/li&gt;
&lt;li&gt;parser CSS dla CSharpStyleProvider - aktualnie style przechowywane w wewnętrznym pliku tekstowym mają postać "nazwaKlasy|wartości", a można by się pokusić o odczytywanie "full-blown" CSS&lt;/li&gt;
&lt;li&gt;implementacja osobnego kolorowania nieparzystych linii&lt;/li&gt;
&lt;li&gt;i wreszcie, co by było chyba rzeczą najfajniejszą z fajnych - implementacja wtyczki do VS która robi to wszystko sama!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kod źródłowy...&lt;/h2&gt;
&lt;p&gt;...zawierający bibliotekę oraz demko WinForms tak jak poprzednimi razy dostępny do ściągnięcia na stronie &lt;a href="http://www.maciejaniserowicz.com/page/Samples.aspx"&gt;SAMPLES&lt;/a&gt;. Z ciekawości można również zajrzeć do kodu źródłowego wspomnianego wcześniej &lt;a href="http://www.manoli.net/csharpformat/" target="_blank"&gt;Manoli formatter&lt;/a&gt;. Cel i efekt te same, mimo że już na etapie koncepcyjnych rozważań obraliśmy inne drogi.&lt;/p&gt;&lt;img src="http://zine.net.pl/aggbug.aspx?PostID=1887" width="1" height="1"&gt;</description><category domain="http://zine.net.pl/blogs/procent/archive/tags/tools/default.aspx">tools</category><category domain="http://zine.net.pl/blogs/procent/archive/tags/sample/default.aspx">sample</category></item><item><title>C# Power ponownie - Control.AllChildControls</title><link>http://zine.net.pl/blogs/procent/archive/2008/08/30/c-power-ponownie-control-allchildcontrols.aspx</link><pubDate>Sat, 30 Aug 2008 20:22:00 GMT</pubDate><guid isPermaLink="false">0de27b5c-4a0c-4e7a-8e19-9d082c99f8a3:1859</guid><dc:creator>Procent</dc:creator><slash:comments>7</slash:comments><comments>http://zine.net.pl/blogs/procent/comments/1859.aspx</comments><wfw:commentRss>http://zine.net.pl/blogs/procent/commentrss.aspx?PostID=1859</wfw:commentRss><wfw:comment>http://zine.net.pl/blogs/procent/rsscomments.aspx?PostID=1859</wfw:comment><description>&lt;p&gt;Podczas przygotowywania kolejnego posta z serii &lt;a href="http://www.maciejaniserowicz.com/?tag=/sample" target="_blank"&gt;"Samples"&lt;/a&gt; zaimplementowało mi się coś bardzo fajnego, co chyba zasługuje na osobną notkę. Oto zatem kolejna krótka demonstracja potęgi połączonych mechanizmów C# (v. 2 i 3).&lt;br /&gt;
Scenariusz: mamy formatkę wypełnioną panelami, groupboxami, layoutami i wszystkimi innymi kontenerami jakie tam jeszcze Bozia z Redmond na toolbox wrzuciła. Nachodzi nas chętka na wykonanie pewnej operacji na WSZYSTKICH kontrolkach zawartych w oknie, niezależnie od tego gdzie są zagnieżdżone. Jak się do nich dobrać? Here comes the beauty of &lt;b&gt;YIELD&lt;/b&gt;:&lt;/p&gt;

&lt;div class="csharp"&gt;
&lt;pre&gt;
&lt;span class="csLineNumber"&gt;  1:&lt;/span&gt;  &lt;span class="csKeyword"&gt;public&lt;/span&gt; &lt;span class="csKeyword"&gt;static&lt;/span&gt; IEnumerable&amp;lt;Control&amp;gt; AllChildControls(&lt;span class="csKeyword"&gt;this&lt;/span&gt; Control instance)
&lt;span class="csLineNumber"&gt;  2:&lt;/span&gt;  {
&lt;span class="csLineNumber"&gt;  3:&lt;/span&gt;  	&lt;span class="csKeyword"&gt;foreach&lt;/span&gt; (Control control &lt;span class="csKeyword"&gt;in&lt;/span&gt; instance.Controls)
&lt;span class="csLineNumber"&gt;  4:&lt;/span&gt;  	{
&lt;span class="csLineNumber"&gt;  5:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;yield&lt;/span&gt; &lt;span class="csKeyword"&gt;return&lt;/span&gt; control;
&lt;span class="csLineNumber"&gt;  6:&lt;/span&gt;  		&lt;span class="csKeyword"&gt;foreach&lt;/span&gt; (Control childControl &lt;span class="csKeyword"&gt;in&lt;/span&gt; control.AllChildControls())
&lt;span class="csLineNumber"&gt;  7:&lt;/span&gt;  			&lt;span class="csKeyword"&gt;yield&lt;/span&gt; &lt;span class="csKeyword"&gt;return&lt;/span&gt; childControl;
&lt;span class="csLineNumber"&gt;  8:&lt;/span&gt;  	}
&lt;span class="csLineNumber"&gt;  9:&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Wykorzystajmy to w jakimś interesującym przypadku... na przykład pod każdy TextBox podepnijmy ToolTipa pokazującego aktualną wartość właściwości Tag. Warunki z tego wynikające są dwa: kontrolka-dziecko musi być TextBoxem i jej Tag nie może być null. &lt;em&gt;&lt;u&gt;Na potęgę posępnego czerepu, LINQ przybywaj!!!&lt;/u&gt;&lt;/em&gt;&lt;/p&gt;


&lt;div class="csharp"&gt;