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

<channel>
	<title>Programowanie &#8211; Strona Szoguna</title>
	<atom:link href="https://szogun1987.pl/show/tag/programowanie/feed/" rel="self" type="application/rss+xml" />
	<link>https://szogun1987.pl</link>
	<description>Jeszcze wstawię tutaj jakiś głęboki cytat</description>
	<lastBuildDate>Sun, 02 Sep 2018 09:27:06 +0000</lastBuildDate>
	<language>pl-PL</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.3.2</generator>
	<item>
		<title>Spotkanie z TaskCompletionSource &#8211; Cz. 1 I promise I will call back</title>
		<link>https://szogun1987.pl/show/spotkanie-z-taskcompletionsource-cz-1-i-promise-i-will-call-back/34/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Thu, 02 Mar 2017 07:55:15 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=34</guid>

					<description><![CDATA[Programowanie asynchroniczne w C# stało całkiem znośne od kiedy język ten posiada słowa kluczowe async i await ... wielu z nas, programistów, jest jednak do dzisiaj zmuszonych pisać asynchronicznie tak jak (nie)potrafi i tak środowisko im na to (nie)pozwala ... Żaden kod napisany przez pierwsze 11 lat istnienia .Net nie miał szans ich użycia. Kod napisany później także niekoniecznie z niego korzysta.


Myślę, że w takiej sytuacji adaptacja starego API na własną rękę może być opłacalna, dlatego postanowiłem popełnić serię artykułów pokazujących jak można się za to zabrać.]]></description>
										<content:encoded><![CDATA[<p>Programowanie asynchroniczne w C# stało całkiem znośne od kiedy język ten posiada słowa kluczowe async i await. Rozwiązanie to tak udało się tak dobrze, że zaczyna pojawiać się w innych językach. VB.Net podobno już je ma (może któryś z czytelników już go używał i mógłby podzielić się swoimi doświadczeniami?), architekci projektujący C++ i Javascript także nad usilnie pracują na wdrożeniem podobnych mechanizmów.</p>
<p><span id="more-34"></span></p>
<p>Wielu z nas, programistów, jest jednak do dzisiaj zmuszonych pisać asynchronicznie tak jak (nie)potrafi i tak środowisko im na to (nie)pozwala. Nawet w C# sytuacja nie wygląda kolorowo, klasa Task umożliwia użycie jej w tandemie z async i await zaledwie od 4 lat. Żaden kod napisany przez pierwsze 11 lat istnienia .Net nie miał szans ich użycia. Kod napisany później także niekoniecznie z niego korzysta.</p>
<p>Myślę, że w takiej sytuacji adaptacja starego API na własną rękę może być opłacalna, dlatego postanowiłem popełnić serię artykułów pokazujących jak można się za to zabrać.<br />
Na szczęście Microsoft szybko zauważył problem adaptacji starego kodu do nowego wzorca, czego efektem jest TaskCompletionSource, który umożliwia przetworzenie czegokolwiek na Task’a.</p>
<p>W pierwszej części chciałbym pokazać adaptację API opartego na kolbakach (ang.callbacks) i obiecankach (ang. Promises).</p>
<p>Wiele angielskich słów nie ma idealnego tłumaczenia, „callback” nie jest tu wyjątkiem. Programiści rozumieją je jako „wywołanie zwrotne”, jednak nikt tak nie mówi, na co dzień używam pięknego słowa „kolbak” i tak będę robił dalej. Dla niewtajemniczonych kolbak opisuje rozwiązanie, w którym metoda jako jeden z argumentów przyjmuje inną metodę, która jest wywoływana po zakończeniu operacji.</p>
<div class="code">
<pre class="prettyprint lang-cs">public void GetNextInt(Action&lt;int&gt; callback)
{
    /* Magic in here */
    callback(123);
}</pre>
</div>
<p>„We will call back to you” w dosłownym tłumaczeniu oznacza „Oddzwonimy do ciebie”. Często to słyszymy, a jak często otrzymujemy telefon gdy coś pójdzie nie tak? I jak się czujemy gdy ktoś długo nie oddzwania? Podobnie czuje się kod i programista, który go napisał, gdy wywołuje metodę z kolbakiem, a ten nigdy nie następuje. Dlatego dobrą praktyką jest przekazanie kodu błędu albo wyjątku jako dodatkowego parametru kolbaka.</p>
<div class="code">
<pre class="prettyprint lang-cs">public void GetNextInt(Action&lt;int, Exception&gt; callback)
{
    try
    {
        /*Magic in here*/
        callback(123, null);
    }
    catch(Exception ex)
    {
        callback(default(int), ex);
    }
}</pre>
</div>
<p>Kolbaki nie są niczym nowym, bo praktycznie każda technologia je wspiera: C++, Javascript, Python, PHP, Java (….aaa nie, przepraszam! Java jednak nie :D), dlatego adaptacja takiej metody do czegoś, co zwróci Taska z wykorzystaniem TaskCompletionSource to nic trudnego.</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task GetNextInt()
{
    var completionSource = new TaskCompletionSource();

    GetNextInt((result, exception) =&gt;
    {
        if (exception != null)
        {
            completionSource.SetException(exception);
        }
        else
        {
            completionSource.SetResult(result);
        }
    });

    return completionSource.Task;
}</pre>
</div>
<p>Taki kod może spowodować przewrócenie się aplikacji. Może się zdarzyć się że callback zostanie wywoływany kilka razy (kompilacja tego nie pilnuje). TaskCompletionSource nie lubi wielokrotnego wywoływania SetException albo SetResult i zgłasza wyjątek. W takim wypadku należy upomnieć twórcę kodu że robi źle, jeżeli to nie pomaga należy użyć środków przymusu bezpośredniego, jak to nie skutkuje należy upewnić się że napisał taki kod ostatni raz. Jeżeli jednak i to jest niemożliwe, ponieważ ktoś już go zdążył zastrzelić należy spróbować zorientować który kolbak jest tym właściwym, jeżeli pierwszy jest dobry wystarczająco to klasa TaskCompletionSource posiada metody TrySetResult i TrySetException, które nie powodują wyjątku przy wielokrotnym wywoływaniu.</p>
<p>Powyższy kod może nie jest może skomplikowany, ale przy pisaniu go 20 raz można się pomylić, dlatego dobrym pomysłem może być napisanie takiego helpera:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task Invoke&lt;T&gt;(Action&lt;T&gt; methodToInvoke)
{
    var completionSource = new TaskCompletionSource&lt;T&gt;();
    methodToInvoke((result, exception) =&gt;
    {
        if (exception != null)
        {
            completionSource.SetException(exception);
        }
        else
        {
            completionSource.SetResult(result);
        }
    });
}</pre>
</div>
<p>Po jego użyciu kod skraca się do:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task GetNextInt()
{
    return Invoke(GetNextInt);
}</pre>
</div>
<p>Kiedy natomiast metoda przyjmuje argumenty:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Task GetNextInt(string argument)
{
    return Invoke((handler) =&gt; GetNextInt(argument, handler));
}</pre>
</div>
<p>Użycie takiego helpera ma sens w sytuacji, kiedy API używa typu Action jako callbacka, ale również w memencie kiedy API używa innego typu (wtedy najlepiej jest użyć go do zmiany typu przyjmowanego jako argument helpera).</p>
<p>Problem zaczyna się gdy API używa callbacków różnego typu, ale jak już wspomniełem nasz staruszek C# ma wiele ograniczeń i nie potrafi „w locie” przetłumaczyć typów oznaczanych słowem delegate, nawet jeżeli mają takie same wejścia i wyjścia. Przykładem może być Action&lt;object, eventarg=&#8221;&#8221;&gt; &#8211; nie da się przekazać tej akcji jako EventHandler. W takiej sytuacji można pisać wszystko z palca, napisać generator kodu lub odpuścić i wyciągnąć jakieś wnioski na przyszłość.&lt;/object,&gt;</p>
<h3>Promise (obiecanki-cacanki)</h3>
<p>Obiecanki to bardzo popularny mechanizm używany w wielu technologiac, w .Net raczej nie występuje, gdyż pojawiło się async/await, jednak można spotkać pewne chałupnicze implementacje. Po co jednak słowa – lepiej będzie, gdy spojrzycie na kod, gdyż wyraża on więcej niż tysiąc słów. Jeżeli w aplikacji występuje taki kod:</p>
<div class="code">
<pre class="prettyprint lang-cs">GetNextInt()
    .OnDone(result =&gt; {
        /* Wyświetl wynik */
        MessageBox.Show("Wynik to " + result);
    }).OnError(error =&gt; {
        MessageBox.ShowError("Coś poszło nie tak.")
    }).Always(() =&gt; {
        /* Schowaj kręcioła */
        HideSpinner();
    });</pre>
</div>
<p>to na 99% GetNextInt zwraca Promise ewentualnie Future. Adaptacja Promise do klasy Task jest nawet łatwiejsza niż kolbaka, sami zobaczcie:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Taks&lt;T&gt; Wrap(this IPromise&lt;T&gt; promise)
{
    var taskCompletionSource = new TaskCompletionSource&lt;T&gt;();
    promise
        .OnDone(result =&gt; {
            taskCompletionSource.SetResult(result)
        }).OnError(error =&gt; {
            taskCompletionSource.SetException(error);
        });
    return taskCompletionSource.Task;
}</pre>
</div>
<p>ale może być jeszcze łatwiejsza:</p>
<div class="code">
<pre class="prettyprint lang-cs">public Taks&lt;T&gt; Wrap&lt;T&gt;(this IPromise&lt;T&gt; promise)
{
    var taskCompletionSource = new TaskCompletionSource&lt;T&gt;();
    promise
        .OnDone(taskCompletionSource.SetResult)
        .OnError(taskCompletionSource.SetException);
    return taskCompletionSource.Task;
}</pre>
</div>
<p>Na dziś – tyle. Jednak to jeszce nie koniec … cdn.</p>
<p>Kod źródłowy projektu stworzonego na potrzeby tego postu udostępniam na <a href="https://github.com/szogun1987/events-and-tasks">Githubie</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>NCrunch &#8211; Jakie to, kurwa, dobre</title>
		<link>https://szogun1987.pl/show/ncrunch-jakie-to-kurwa-dobre/31/</link>
					<comments>https://szogun1987.pl/show/ncrunch-jakie-to-kurwa-dobre/31/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sat, 10 Oct 2015 09:19:04 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=31</guid>

					<description><![CDATA[Cytatem Youtubowego kucharza (Food Emperor) polecam wszystkim narzędzie wniesione do zespołu, w kt&#243;rym pracuję, przez nowego kolegę Sebastiana.



&#160;

]]></description>
										<content:encoded><![CDATA[<p>Cytatem Youtubowego kucharza (<a href="https://www.youtube.com/user/FoodEmperor">Food Emperor</a>) polecam wszystkim narzędzie wniesione do zespołu, w którym pracuję, przez nowego kolegę Sebastiana.</p>
<p>Wiem że o NCrunchu pisało już wielu. Jednak nikomu nie udało się mnie do niego przekonać, więc jest pewnie wielu innych sceptyków tego narzędzia i do nich właśnie jest ten artykuł.<br />
Jest to narzędzie pełniące rolę sumienia dla osób stosujących TDD. Każda linijka kodu C#-owego jest oznaczona kropą: białą gdy brakuje testów ją pokrywajacych, czerwoną gdy jakiś test nie przechodzi i zieloną gdy wszystko jest OK.<br />
<img decoding="async" style="height: 146px; width: 370px;" src="http://static.szogun1987.pl/img/ncrunch/TrzyKropy.png" alt="Działanie NCruncha" /></p>
<p><span id="more-31"></span></p>
<h2>Skąd Ncrunch wie, że test nie przechodzi?</h2>
<p>Po prostu uruchamia wszystkie testy w tle.</p>
<h2>Więc co z wydajnością?</h2>
<p>Jeszcze nie tego nie odczułem ale podejrzewam że będzie to kłopot. Na szczęście ncrunch nie pozostawia nas samych z tym problemem. Linijki uruchamiające się szczególnie długo są oznaczone jaśniejszym zielonym przechodzącym w żółty. Często są to miejsca w kodzie generujące efekty uboczne zmiany w bazie, zapis na dysku. Istnieje też możliwość wyłączenia części testów z uruchamiania w tle. Swoją drogą chyba za długo przebywam w towarzystwie fanów apple bo zaczynam rozpoznawać kolory.<br />
<img decoding="async" style="height: 71px; width: 243px;" src="http://static.szogun1987.pl/img/ncrunch/ZolteKropy.png" alt="Oznaczenie wolnych linijek" /></p>
<h2>I to wszystko za darmo?</h2>
<p>Niestety nie. NCrunch kosztuje i to całkiem sporo, w dodatku subskrypcję trzeba odnawiać co rok. Prawdopodobnie łatwiej wam będzie namówić szefa niż samemu rozstać się z taką sumką. Oczywiście jak każdy dobry dealer twórca NCruncha daje pierwszą działkę gratis. Osobiście gdy tylko Trial się skończy zakupię sobie licencję (chcę z niego korzystać także po za pracą).</p>
<p>I pamiętajcie &#8222;To jest takie dobre, że gdy rozwiązujecie zadanie, testerka już robi się mokra&#8221;.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/ncrunch-jakie-to-kurwa-dobre/31/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Gdy HtmlHelper to za mało</title>
		<link>https://szogun1987.pl/show/gdy-htmlhelper-to-za-malo/28/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sat, 13 Sep 2014 10:46:19 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=28</guid>

					<description><![CDATA[Czytając ostatnio o rozszerzeniach do klasy HtmlHelper, stwierdziłem że w wraz z rozwojem projektu ich r&#243;żnorodność może stać się trudna do ogarnięcia i przydałoby się je pogrupować, zorganizować.
Zacząłem się więc zastanawiać jak takie rozwiązanie mogłoby wyglądać. Zaznaczam przy tym że sam tego jeszcze nie doświadczyłem, a koncepcje dalej przedstawione są raczej propozycjami niż wskaz&#243;wkami.

]]></description>
										<content:encoded><![CDATA[<p>Czytając ostatnio o rozszerzeniach do klasy HtmlHelper, stwierdziłem że w wraz z rozwojem projektu ich różnorodność może stać się trudna do ogarnięcia i przydałoby się je pogrupować, zorganizować.<br />
Zacząłem się więc zastanawiać jak takie rozwiązanie mogłoby wyglądać. Zaznaczam przy tym że sam tego jeszcze nie doświadczyłem, a koncepcje dalej przedstawione są raczej propozycjami niż wskazówkami.</p>
<p><span id="more-28"></span></p>
<p>Pierwszym narzucającym się rozwiązaniem jest konwencja nazewnicza, najlepiej przedrostkowa. Aby uniknąć zbyt długiego komentarza po prostu wstawię fragment kodu tworzonego w ten sposób.</p>
<pre class="prettyprint lang-cs">@using(Html.BootstrapGridRow())
{
	@using(Html.BootstrapGridCol(4))
	{
		<!-- zawartość kolumny -->
	}
	@using(Html.BootstrapGridCol(8))
	{
		<!-- zawartość drugiej kolumny -->
	}
}
</pre>
<p>Kod powyższych Helperów nie różni się niczym od kodu Helperów jakie tworzy każdy kto chociaż chwilę pracował w MVC.</p>
<p>Jest to rozwiązanie które znacząco ułatwia szukanie interesującego Helpera, zwłaszcza po usprawnieniach w Intellisense obecnych w Visual Studio od wersji 2010 i zwłaszcza przez osobę która kilka tygodni spędziła już w zespole. Rozwiązanie to nie chroni jednak przed literówkami lub łamaniem konwencji więc zacząłem się zastanawiać czy nie da się tego zrobić lepiej.</p>
<p>Drugim pomysłem jest stworzenie helperów które zamiast IDisposable i HtmlString zwracają klasę która zawiera takie metody. Użycie takiego API wyglądałoby następująco:</p>
<pre class="prettyprint lang-cs">@using(Html.Bootstrap().GridRow())
{
	@using(Html.Bootstrap().GridCol(4))
	{
		<!-- zawartość kolumny -->
	}
	@using(Html.Bootstrap().GridCol(8))
	{
		<!-- zawartość drugiej kolumny -->
	}
}
</pre>
<p>W tym podejściu na start w Intellisense widzimy tylko Helpery tworzące Grupy zamiast widzieć wszystkie metody. Wadą tego rozwiązania jest trochę mniej przejrzysty kod samych Helperów.</p>
<pre class="prettyprint lang-cs">public static class BootstrapHelper
{
	public static GroupingClass Bootstrap(this HtmlHelper self)
	{
		return new GroupingClass(self);
	}

	public class GroupingClass
	{
		private HtmlHelper helper;

		public GroupingClass(HtmlHelper helper)
		{
			this.helper = helper;
		}

		public IDisposable GridRow()
		{
			// TODO: zwrócić co trzeba
		}

		public IDisposable GridCol(int width)
		{
			// TODO: Zrobić co trzeba
		}
	}
}
</pre>
<p>Oczywiście nazwa klasy GroupingClass została wymyślona na szybko ze względu na brak lepszego pomysłu</p>
<p>Na koniec stwierdziłem że ten Html na początku i te nawiasy są niepotrzebnymi ozdobnikami i najfajniej by było jakbym mógł napisać po prostu:</p>
<pre class="prettyprint lang-cs">@using(Bootstrap.GridRow())
{
	@using(Bootstrap.GridCol(4))
	{
		<!-- zawartość kolumny -->
	}
	@using(Bootstrap.GridCol(8))
	{
		<!-- zawartość drugiej kolumny -->
	}
}
</pre>
<p>Okazuje się że jest to możliwe wymaga jednak trochę więcej gimnastyki. I wiedzy jak działa Razor. Okazuje się że działa on bardzo podobnie do silnika wykorzystywanego w WebForms. Każdy widok jest kompilowany podczas działania aplikacji do klasy dziedziczącej po System.Web.Mvc.WebViewPage &#8211; dla nietypowanych widoków, albo System.Web.Mvc.WebViewPage&lt;TView&gt; dla widoków typowanych. Właściwości Html, Ajax itp. pochodzą z tych właśnie klas. Klasą bazową dla kompilowanych w locie klas może być jednak inna klasa, którą można ustawić w sekcji configuration &#8211; system.web.webPages.razor &#8211; page w atrybucie pageBaseType w Web.configu, jednak nie tym Web.configu w głównym folderze aplikacji, a tym w katalogu Views.<br />
Klasa ta powinna występować w dwóch formach (generycznej i nie) i dziedziczyć po WebViewPage. Klasa powinna być abstrakcyjna (implementację metody Execute zostawiamy widokowi).</p>
<pre class="prettyprint lang-cs">public abstract class CustomWebViewPage : WebViewPage
{
	protected CustomWebViewPage()
	{
		Bootstrap = new BootstrapHelper(ViewContext);
	}

	public BootstrapHelper Bootstrap { get; private set; }
}

public abstract class CustomWebViewPage : WebViewPage
{
	protected CustomWebViewPage()
	{
		Bootstrap = new BootstrapHelper(ViewContext);
	}

	public BootstrapHelper Bootstrap { get; private set; }
}

public class BootstrapHelper
{
	private ViewContext viewContext;

	public BootstrapHelper(ViewContext viewContext)
	{
		this.viewContext = viewContext;
	}

	public IDisposable GridRow()
	{
		// TODO: zwrócić co trzeba
	}

	public IDisposable GridCol(int width)
	{
		// TODO: Zrobić co trzeba
	} 
}
</pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Sqlite &#8211; agregacja bez group by</title>
		<link>https://szogun1987.pl/show/sqlite-agregacja-bez-group-by/27/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Thu, 17 Jul 2014 20:30:38 +0000</pubDate>
				<category><![CDATA[Programowanie]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=27</guid>

					<description><![CDATA[Kr&#243;tki wpis o błędzie znalezionym przeze mnie w Sqlite.

]]></description>
										<content:encoded><![CDATA[<p>Kr&oacute;tki wpis o błędzie znalezionym przeze mnie w Sqlite.</p>
<p>Jeżeli w zapytaniu umieści się funkcję agregacyjną i zwykłą kolumnę, a w zapytaniu nie wstawi się group by to zapytanie wykona się bez zgłoszenia błędu. Wynikiem takiego zapytania będzie jeden wiersz w kt&oacute;rym funkcja agregacyjna zwr&oacute;ci poprawną wartość natomiast w kolumnie wyciągniętej ze &quot;zwykłej&quot; kolumny znajdzie się jakaś &nbsp;wartość (prawdopodobnie pierwsza z brzegu). W SQL Serverze po prostu się wywala w innych silnikach nie sprawdzałem.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Amatorskie spojrzenie na EmguCV</title>
		<link>https://szogun1987.pl/show/amatorskie-spojrzenie-na-emgucv/19/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Tue, 10 Jun 2014 20:43:35 +0000</pubDate>
				<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[EmguCV]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=19</guid>

					<description><![CDATA[EmguCV jest .Netowym wrapperem do OpenCV - potężnej biblioteki do przetwarzania i analizy obraz&#243;w (zar&#243;wno statycznych jak i ruchomych) oraz innych sygnał&#243;w cyfrowych.



Ważną cechą biblioteki jest fakt iż stara się ona wykorzystać jak najlepiej zasoby dostępne na maszynie na kt&#243;rej jest ona uruchomiona, ze szczeg&#243;lnym uwzględnieniem karty grafiki.

]]></description>
										<content:encoded><![CDATA[<p>EmguCV jest .Netowym wrapperem do OpenCV &#8211; potężnej biblioteki do przetwarzania i analizy obraz&oacute;w (zar&oacute;wno statycznych jak i ruchomych) oraz innych sygnał&oacute;w cyfrowych.</p>
<p>Ważną cechą biblioteki jest fakt iż stara się ona wykorzystać jak najlepiej zasoby dostępne na maszynie na kt&oacute;rej jest ona uruchomiona, ze szczeg&oacute;lnym uwzględnieniem karty grafiki.</p>
<p>Opr&oacute;cz tego OpenCV wspiera machine learning, jednak tej części biblioteki jeszcze nie dotykałem.</p>
<p>Co ma wsp&oacute;lnego programista .Net zajmujący się nudnymi dokumentami korporacyjnymi z przetwarzaniem obraz&oacute;w? Niewiele. Po prostu od czasu do czasu trzeba spr&oacute;bować czegoś nowego for-fun więc znalazłem pierwszy lepszy pretekst żeby pobawić się się EmguCV.</p>
<p>Od razu zaznaczę, że nie czytałem o żadnych dobrych praktykach, ani nawet nie zagłębiałem się w tutoriale tylko postanowiłem rozpocząć naukę przez eksplorację wspartą przez google i stackoverflow. W dodatku skoncentrowałem się tylko na podstawowych przekształceniach obraz&oacute;w statycznych.</p>
<h1>1. Instalacja</h1>
<p>Instalację należy zacząć od wejścia na stronę <a href="http://sourceforge.net/projects/emgucv/">http://sourceforge.net/projects/emgucv/</a> i pobrania instalatora i klikania next, next, next. Już sam rozmiar paczki instalacyjnej robi wrażenie (200+MB), Natomiast po jej zainstalowaniu stracimy prawie 2GB dysku. Liczbę tą można zmniejszyć rezygnując z instalacji przykładowych solucji.</p>
<h1>2. Pierwsze podpięcie</h1>
<p>Podłączenie Emgu do solucji w celu przekształcania obraz&oacute;w statycznych jest opisane na stronie <a href="http://www.emgu.com/wiki/index.php/Setting_up_EMGU_C_Sharp">http://www.emgu.com/wiki/index.php/Setting_up_EMGU_C_Sharp</a> zgodnie z tym tutorialem należy do swojego projektu dodać referencje do dll&rsquo;ek EmguCV.dll, EmguCV.UI.dll oraz EmguCV.Util.dll biblioteki te znajdują się w katalogu &ldquo;&lt;ścieżka_do_emgu&gt;\bin&rdquo;.</p>
<p>Biblioteki te nie są jednak samodzielnymi bibliotekami tylko wrapperami do bibliotek napisanych w c++ kt&oacute;re posiadają wersje 32 i 64 bitową co za tym idzie nasza aplikacja albo będzie miała 2 wersje albo nie będzie działać na niekt&oacute;rych stacjach roboczych.</p>
<p>Powoduje to że powinniśmy ustawić właściwość &ldquo;Target platform&rdquo; na &ldquo;x64&rdquo; (Properties w naszym csproj, zakładka Build).</p>
<p>Drugim problemem o kt&oacute;rym wspomniany wcześniej tutorial nie m&oacute;wi to fakt iż zależności między bibliotekami się trochę pozmieniały i dodanie do projektu tylko i wyłącznie opencv_core&lt;ver&gt;.dll i opencv_imgproc&lt;ver&gt;.dll (znajdujacych się w katalogu &nbsp;&ldquo;&lt;ścieżka_do_emgu&gt;\bin\x64&rdquo;) sprawi że po wykorzystaniu jakiejkolwiek metody z biblioteki EmguCV dostaniemy w twarz błędem o mało m&oacute;wiącym komunikacie &ldquo;&#39;System.TypeInitializationException&#39; occurred in Emgu.CV.dll&rdquo;. Grzebiąc po internecie znalazłem poradę aby po prostu przekopiować cały katalog &ldquo;&lt;ścieżka_do_emgu&gt;\bin\x64&rdquo; do swojej solucji tak aby lądował w katalogu bin\Debug wadą tego rozwiązania jest jednak fakt iż cały katalog waży 566MB. Jeżeli ktoś zna minimalny podzbi&oacute;r dll&rsquo;ek potrzebny do otworzenia obrazu z pliku i wyświetlenia go w Picturebox będę wdzięczny.</p>
<h1>3. Pokaż cy&hellip;kod</h1>
<p>Podstawową klasą z kt&oacute;rej korzystałem podczas moich zabaw jest Image&lt;TColor, TDepth&gt; jak widać jest to klasa generyczna pierwszy parametr oznacza w jaki spos&oacute;b można operować na kolorach obrazu. Przykładami typ&oacute;w kt&oacute;re można tam postawić są Bgr, Gray, Bgr556, Hsv i kilka innych. Parametr TDepth oznacza typ używany do określenia głębi kolor&oacute;w (osobiście zawsze tam wrzucam byte).</p>
<p>Klasa ta posiada kilka kontruktor&oacute;w z kt&oacute;rych według mnie najważniejsze to:</p>
<p>public Image(Bitmap bmp);</p>
<p>Służy do konwesji bitmapy z przestrzeni nazw System.Drawing na obraz kt&oacute;ry nadaje się do przetworzenia przez Emgu.</p>
<pre class="prettyprint lang-cs">public Image(string fileName)</pre>
<p>Pozwala otworzyć obraz z pliku, metoda nie wspiera format&oacute;w Uri, jednak wnioskując po treści zgłaszanego wyjątku obsługa taka zostanie dodana</p>
<pre class="prettyprint lang-cs">public Image(int width, int height, TColor value);</pre>
<p>Tworzy obraz o zadanych wymiarach i kolorze</p>
<p>Niestety pośr&oacute;d konstruktor&oacute;w brakuje otwarcia obrazu z dowolnego strumienia, jednak można się posiłkować następującym obejściem:</p>
<pre class="prettyprint lang-cs">
using (Stream stream = new SomeStream())
            {
                using (var memoryStream = new MemoryStream())
                {
                    stream.CopyTo(memoryStream);
                    memoryStream.Position = 0;

                    Image<Bgr, byte> image = Image<Bgr, byte>.FromRawImageData(memoryStream.ToArray());
                }
            }

</pre>
<p>Klasa Image zawiera szereg metod kt&oacute;re można podzielić na dwie grupy:</p>
<ul>
<li>
<p>zaczynające się od podkreślenia &#8211; zmieniają obiekt obrazu na kt&oacute;rym są wywoływane</p>
</li>
<li>
<p>nazywające się jak pan B&oacute;g przykazał &#8211; generują kopię obrazu z naniesionymi zmianami</p>
</li>
</ul>
<p>Część metod posiada wersję z podkreśleniem i bez. Intuicja mi podpowiada że metody &ldquo;podkreślnikowe&rdquo; są wydajniejsze ale nie są nie można ich używać bezpiecznie w środowisku wielowątkowym (nie szukałem jednak potwierdzenia tej tezy w dokumentacji).</p>
<p>Pierwszą metodą w klasie Image, kt&oacute;rą postanowiłem przybliżyć jest Convert&lt;TColor, TDepth&gt; &nbsp;metoda da pozwala na stworzenie obrazu opisanego w inny spos&oacute;b lub mającego inną głębię.</p>
<pre class="prettyprint lang-cs">
// Dzięki temu możemy operować na głębi i nasyceniu kolor&oacute;w
var image2 = image.Convert&lt;Hsv, byte&gt;();
// Konwersja na skalę szarości - nieodwracalna
var image3 = image.Convert&lt;Gray, byte&gt;();
</pre>
<p>
Drugą ważną dla mnie metodą jest .ToBitmap pozwalająca konwertować obraz do klasy System.Drawing.Bitmap co pozwala wyświetlić wynik przekształceń w kontrolkach Windows Forms.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Eclipse Database Development Incorrect syntax w poprawnym skrypcie</title>
		<link>https://szogun1987.pl/show/eclipse-database-development-incorrect-syntax-w-poprawnym-skrypcie/18/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sun, 01 Jun 2014 09:22:20 +0000</pubDate>
				<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=18</guid>

					<description><![CDATA[Eclipse Database Development Tools to całkiem fajne narzędzie do wsp&#243;łpracy z SQL-owymi bazami danych. Posiada kolorwanie składni, możliwość edycji danych w tabelkach, jest zintegrowane z Eclipsem, działa z każdym silnikiem SQL z jakiego kiedykolwiek korzystałem, a co najważniejsze jest dostępne za free.



Jednak podczas przenoszenia bloga na nowy hosting i domenę przytrafiła mi się przykre doświadczenie. Pr&#243;bowałem z tego narzędzia odpalić skrypt migrujący dane. I zamiast pełnej bazy zobaczyłem komunikat o niepoprawnej składni.

]]></description>
										<content:encoded><![CDATA[<p>Eclipse Database Development Tools to całkiem fajne narzędzie do wsp&oacute;łpracy z SQL-owymi bazami danych. Posiada kolorwanie składni, możliwość edycji danych w tabelkach, jest zintegrowane z Eclipsem, działa z każdym silnikiem SQL z jakiego kiedykolwiek korzystałem, a co najważniejsze jest dostępne za free.</p>
<p>Jednak podczas przenoszenia bloga na nowy hosting i domenę przytrafiła mi się przykre doświadczenie. Pr&oacute;bowałem z tego narzędzia odpalić skrypt migrujący dane. I zamiast pełnej bazy zobaczyłem komunikat o niepoprawnej składni.</p>
<p>Okazuje się że przy odpaleniu dłuższych skrypt&oacute;w narzędzie to najpierw robi paskudne dzielenie skryptu po średnikach nie patrząc gdzie one się znajdują a następnie uruchamia skrypt po skrypcie.</p>
<p>Ponieważ m&oacute;j Blog jest programistyczny napisy zawierały spore ilości średnik&oacute;w. Skończyło się na zassaniu skryptu przez konsolę.&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Lazy Yield Problems</title>
		<link>https://szogun1987.pl/show/lazy-yield-problems/17/</link>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sat, 22 Feb 2014 23:00:00 +0000</pubDate>
				<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=17</guid>

					<description><![CDATA[Zanim przejdę do sedna sprawy nakreślę najpierw ciąg wydarzeń który mnie ku napisaniu tego posta skłonił. 
Ostatnimi czasy wykonywałem małą biblioteczkę "na własne potrzeby" kt]]></description>
										<content:encoded><![CDATA[<p>Zanim przejdę do sedna sprawy nakreślę najpierw ciąg wydarzeń kt&oacute;ry mnie ku napisaniu tego posta skłonił. </p>
<p>Ostatnimi czasy wykonywałem małą biblioteczkę &quot;na własne potrzeby&quot; kt&oacute;rej podstawą był interfejs kt&oacute;ry można przedstawić następująco:</p>
<div class="code">
<pre class="prettyprint lang-cs">
public interface IProcessor&lt;T&gt;
{
	IEnumerable&lt;Result&gt; Process(T input);
}
</pre>
</div>
</p>
<p>Interfejs ten ma wiele implementacji jednak z punktu widzenia tego postu kluczowy jest &quot;AggregateProcessor&quot; kt&oacute;ry łączy wyniki  kilku procesor&oacute;w.</p>
<div class="code">
<pre class="prettyprint lang-cs">
class AggregateProcessor&lt;T&gt; : IProcessor&lt;T&gt;
{
	private IProcessor&lt;T&gt;[] subProcessors;

	public AggregateProcessor(params IProcessor&lt;T&gt;[] subProcessors)
	{
		this.subProcessors = subProcessors;
	}

	public IEnumerable&lt;Result&gt; Process(T input)
	{
		return subProcessors.SelectMany(p =&gt; p.Process(input));

		/* ekwiwalent
		foreach (var processor in subProcessors)
		{
			foreach (var result in processor.Process(input))
			{
				yield return result;
			}
		}
		 */
	}
}
</pre>
</div>
</p>
<p>Następnie dla tej klasy napisałem prosty test sprawdzający czy podprocesor zostanie wywołany po wywołaniu Process na AggregateProcessorze.</p>
<p>Test jest napisany w NUnicie do Mockowania wykorzystałem FakeItEasy.</p>
</p>
<div class="code">
<pre class="prettyprint lang-cs">
[Test]
public void CheckIfSubProcessorIsCalled()
{
	// Given
	var parameter = new TestClass();

	var fakeProcessor = A.Fake&lt;IProcessor&lt;TestClass&gt;&gt;();
	A.CallTo(() =&gt; fakeProcessor.Process(parameter)).Returns(Enumerable.Empty&lt;Result&gt;());

	var aggregate = new AggregateProcessor&lt;TestClass&gt;(fakeProcessor);

	// When
	aggregate.Process(parameter);

	// Then
	A.CallTo(() =&gt; fakeProcessor.Process(parameter)).MustHaveHappened();
}
</pre>
</div>
</p>
<p>Wielkie było moje zdziwienie gdy okazało się że Test nie przechodzi.</p>
</p>
<p>Przyczyną tej sytuacji jest fakt iż zar&oacute;wno operacje w zapytaniu LINQ jak i operacja yield wywoływane są w momencie iteracji po wyniku metody kt&oacute;rej w tym przykładzie nie ma. W większości przypadk&oacute;w fakt ten nie ma większego znaczenia ponieważ iteracja zazwyczaj w końcu następuje, chyba że tak jak w tym przypadku metody będącej funkcją używamy jak metody będącej procedurą, albo wykonujemy na wyniku operacje typu Any, First/FirstOrDefault kt&oacute;re nie iterują po całym wyniku.</p>
<p>Wracając do mojego przypadku ostatecznie stwierdziłem że fakt wywołania metody wewnętrznej nie jest dla mnie istotny, a bardziej obchodzi mnie zwr&oacute;cenie wyniku procesora wewnętrznego.</p>
</p>
<div class="code">
<pre class="prettyprint lang-cs">
[Test]
public void CheckIfSubProcessorIsCalled()
{
	// Given
	var parameter = new TestClass();
	var result = new Result();

	var fakeProcessor = A.Fake&lt;IProcessor&lt;TestClass&gt;&gt;();
	A.CallTo(() =&gt; fakeProcessor.Process(parameter)).Returns(new[] { result });

	var aggregate = new AggregateProcessor&lt;TestClass&gt;(fakeProcessor);

	// When
	var resultCollection = aggregate.Process(parameter);

	// Then
	CollectionAssert.Contains(resultCollection, result);
}
</pre>
</div>
</p>
<p>Drugim zagrożeniem jakie wiąże się z yield i LINQ jest fakt iż wszystkie operacje wykonywane pod spodem wykonują się przy każdej iteracji po wynikowej kolekcji. Sam się na tym nigdy nie przejechałem ponieważ przed błędem tego typu skutecznie chroni mnie Resharper, jednak ludzi nie posiadających tego genialnego narzędzia warto ostrzec że poniższy kod:</p>
<div class="code">
<pre class="prettyprint lang-cs">
static void Main(string[] args)
{
	var sourceCollection = Enumerable.Range(1, 10);

	var resultCollection = from number in sourceCollection
						   select Compute(number);

	foreach (var number in resultCollection)
	{
		Console.Write(&quot;{0}, &quot;, number);
	}

	Console.WriteLine();

	foreach (var number in resultCollection)
	{
		Console.Write(&quot;{0}, &quot;, number);
	}
}

private static int Compute(int parameter)
{
	// Some Heavy operation
	Thread.Sleep(1000);
	return parameter + 1;
}
</pre>
</div>
<p>będzie uruchamiał się 20 a nie 10 sekund. Jakimś obejściem tego problemu jest użycie metody ToList. Najlepiej w następujący spos&oacute;b:</p>
<div class="code">
<pre class="prettyprint lang-cs">
static void Main(string[] args)
{
	var sourceCollection = Enumerable.Range(1, 10);

	var resultCollection = from number in sourceCollection
						   select Compute(number);

	/*
	 * Przed wywołaniem ToList upewniam się że kolekcja nie jest już listą
	 * W tym przypadku nie ma to sensu ponieważ wiem że kolekcja nie jest listą
	 */
	var resultList = resultCollection as List&lt;int&gt; ?? resultCollection.ToList();

	foreach (var number in resultList)
	{
		Console.Write(&quot;{0}, &quot;, number);
	}

	Console.WriteLine();

	foreach (var number in resultList)
	{
		Console.Write(&quot;{0}, &quot;, number);
	}
}
</pre>
</div>
</p>
<p>Podsumowując zar&oacute;wno LINQ jak i yield są bardzo fajnymi narzędziami, przed ich użyciem należy jednak przynajmniej w minimalnym stopniu dowiedzieć się jak one&nbsp;działają.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Świąteczne małpki</title>
		<link>https://szogun1987.pl/show/swiateczne-malpki/16/</link>
					<comments>https://szogun1987.pl/show/swiateczne-malpki/16/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sat, 24 Dec 2011 23:00:00 +0000</pubDate>
				<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=16</guid>

					<description><![CDATA[W ostatnim czasie w pracy spotkałem się z problemem który w uproszczeniu wygląda następująco:
Mamy listę obiektów typu Dział zawierających kolekcje obiektów typu Wydział zawiera]]></description>
										<content:encoded><![CDATA[<p>W ostatnim czasie w pracy spotkałem się z problemem kt&oacute;ry w uproszczeniu wygląda następująco:</p>
<p>Mamy listę obiekt&oacute;w typu Dział zawierających kolekcje obiekt&oacute;w typu Wydział zawierających kolekcję obiekt&oacute;w typu pracownik. Problemem do rozwiązania jest policzenie średniej Wieku wszystkich pracownik&oacute;w. Zakładamy dodatkowo że baza nie jest tuż za płotem tylko znajduje się za WebServicem do kt&oacute;rego dokładanie metod jest z jakiś przyczyn problematyczne, więc nie możemy po prostu złożyć składnego selecta.</p>
<p>Problem wydaje się być banalny wystarczy zmontować coś takiego:</p>
<div class="code">
<pre class="prettyprint lang-cs">
int ilosc = 0;
            int suma = 0;

            foreach (Dzial dzial in dzialy)
            {
                foreach (Wydzial wydzial in dzial.Wydzialy)
                {
                    foreach (Pracownik pracownik in wydzial.Pracownicy)
                    {
                        ilosc++;
                        suma += pracownik.Wiek;
                    }
                }
            }

            double wynik = ((float)suma) / ilosc;
</pre>
</div>
<p>Jest to jednak kod mało czytelny. A jeżeli operacja byłaby bardziej złożona niż średnia robi się jeszcze mniej ciekawie.</p>
<p>Rozwiązaniem jakie narzuca się bardziej doświadczonym programistom .Net jest użycie LINQ. Rozwiązanie to ma jednak wadę: nie chodzi na kolekcjach kolekcji tylko na jednowarstwowych kolekcjach. Można ten problem rozwiązać przez wyliczenie sobie pomocniczej kolekcji i na niej wykonania działania:</p>
<div class="code">
<pre class="prettyprint lang-cs">
           List&lt;Pracownik&gt; pracownicy = new List&lt;Pracownik&gt;();

            foreach (Dzial dzial in dzialy)
            {
                foreach (Wydzial wydzial in dzial.Wydzialy)
                {
                    foreach (Pracownik pracownik in wydzial.Pracownicy)
                    {
                        pracownicy.Add(pracownik);
                    }
                }
            }

            double wynik = pracownicy.Average(p =&gt; p.Wiek);
</pre>
</div>
<p>Jest to rozwiązanie dobre jednak tworzenie i napełnianie listy w przypadku dużych kolekcji może okazać się zasobożerne.</p>
<p>Dlatego też postanowiłem zrobić świąteczny prezent sobie i innym programistom i stworzyć małpkę kt&oacute;ra za nas będzie biegała po drzewach i strukturach drzewo-podobnych. W ten spos&oacute;b powstało rozszerzenie ExtractSubCollection biblioteki Szogun1987.Monkey. Po wykorzystaniu tej metody powyższy kod zostaje skr&oacute;cony do 4 w miarę czytelnych linijek:</p>
<div class="code">
<pre class="prettyprint lang-cs">
double result = 
                dzialy.ExtractSubCollection(d =&gt; d.Wydzialy)
                .ExtractSubCollection(w =&gt; w.Pracownicy)
                .Average(p =&gt; p.Wiek);
</pre>
</div>
</p>
<p>W bibliotece znajdują się dodatkowo rozszerzenia GetAllSubNodes, GetLeafs i GetRoot ułatwiające przeglądanie zwykłych (tj. składających się z węzł&oacute;w sp&oacute;jnych pod względem typu) Drzew.</p>
<p>Najprostszą z nich jest GetRoot kt&oacute;ra jako parametr pobiera obiekt &#8211; węzeł drzewa i Funkcję zwracającą element nadrzędny węzła. Jako korzeń uznawany jest element dla kt&oacute;rego powyższa funkcja zwr&oacute;ci null.</p>
<p>Kolejną metodą jest GetAllSubNodes pozwala ona na przeiterowanie po wszystkich węzłach znajdujących się poniżej węzła na kt&oacute;rym wywoływane jest rozszerzenie (łącznie z nim samym).  Jako drugi parametr przyjmowana jest funkcja zwracająca kolekcję element&oacute;w podrzędnych.</p>
<p>Ostatnią metodą w bibliotece jest GetLeafs pozwalająca przeiterować się po liściach drzewa z niego się wywodzących.</p>
<p>Dodatkowo w bibliotece znajduje się interfejs ITreeNode kt&oacute;rego zaimplementowanie sprawia że do funkcji GetAllSubNodes, GetLeafs i GetRoot nie trzeba przekazywać funkcji wyciągających &quot;najbliższych członk&oacute;w rodziny&quot; danego elementu.</p>
</p>
<p>Dołożyłem starań aby biblioteka była napisana w spos&oacute;b powodujący jak najniższe zużycie zasob&oacute;w systemowych (pamięci i procesora). Podobnie jak w LINQ wszelkie funkcje i metody przekazywane do moich rozszerzeń są wywoływane w momencie iteracji.</p>
</p>
<p>Na koniec kwestie prawne, (Co by było wszystko na papierze znaczy się monitorze):</p>
<p>Zezwalam na nieodpłatne korzystanie ze skompilowanej wersji biblioteki. Biorę na siebie poprawki ewentualnie wykrytych błęd&oacute;w, przy czym nie naprawiam błęd&oacute;w wynikających ze wsp&oacute;łbieżnego dostępu do drzewa. Nie gwarantuję także wprowadzania ulepszeń.</p>
<p>Kodu źr&oacute;dłowego nie udostępnię w tym roku. Zakładam taką możliwość w pierwszym kwartale roku przyszłego (2012).</p>
</p>
<p>Biblioteki są do pobrania <a href="http://static.szogun1987.pl/upload/Monkey.zip" target="_blank">Tutaj</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/swiateczne-malpki/16/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Problem zwrotnych referencji w WCF</title>
		<link>https://szogun1987.pl/show/problem-zwrotnych-referencji-w-wcf/15/</link>
					<comments>https://szogun1987.pl/show/problem-zwrotnych-referencji-w-wcf/15/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sat, 30 Jul 2011 22:00:00 +0000</pubDate>
				<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=15</guid>

					<description><![CDATA[Podczas wielu batalii z WCF'em natknąłem się na konieczność umieszczenia w obiekcie będącej elementem jakiejś kolekcji referencji do obiektu posiadającego tą kolekcję. ]]></description>
										<content:encoded><![CDATA[<p>Podczas wielu batalii z WCF&#039;em natknąłem się na konieczność umieszczenia w obiekcie będącej elementem jakiejś kolekcji referencji do obiektu posiadającego tą kolekcję. (Przyznam że konieczność ta była związana z faktem iż w przesyłanej klasie była zaszyta część logiki biznesowej a tak się nie powinno robić ale jak mus to mus). Tak więc posiadałem DataContract&#039;y podobne do tych:</p>
<div class="code">
<pre class="prettyprint lang-cs">
    [DataContract]
    public class Parent
    {
        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public List&lt;Children&gt; Childrens { get; set; }
    }

    [DataContract]
    public class Children
    {
        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public Parent Parent { get; set; }
    }
</pre>
</div>
</p>
<p>Pr&oacute;ba pobrania obiektu Parent zakończyła się błędem:</p>
<p><img decoding="async" src="http://static.szogun1987.pl/pictures/WCFBlad1.png" alt="WCFBlad1.png"/></p>
<p>Znalezienie przyczyny błędu było na tyle trudniejsze że pomiędzy buildem a napisaniem DataContractu robiłem całą masę innych rzeczy.</p>
<p>Błąd ten jest spowodowany wyjątkiem StackOverflow po stronie serwera, wynika on z faktu że przy pr&oacute;bie serializacji klasy Children mechanizm docierając do pola Parent nie orientuje się że już ten obiekt serializował albo właśnie go serializuje.</p>
<p>Rozwiązaniem tego problemu jakie znalazłem googlając było ustawienie właściwości IsReference w klasie rodzica i rzeczywiście w tak prostym przypadku rozwiązanie to działa jak należy.</p>
<div class="code">
<pre class="prettyprint lang-cs">
    [DataContract(IsReference=true)]
    public class Children
    {
        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public Parent Parent { get; set; }
    }
</pre>
</div>
</p>
<p>Moja sytuacja była jednak trochę bardziej złożona. Po pierwsze zar&oacute;wno Parent jak i Children dziedziczyło po jednym typie bazowym:</p>
<div class="code">
<pre class="prettyprint lang-cs">
    [KnownType(typeof(ChildrenBP))]
    [KnownType(typeof(ParentBP))]
    [DataContract]
    public class SuperBP
    {
        [DataMember]
        public string Name { get; set; }
    }
    
    [DataContract(IsReference=true)]
    public class ParentBP : SuperBP
    {
        [DataMember]
        public List&lt;ChildrenBP&gt; Childrens { get; set; }
    }
	
	[DataContract]
    public class ChildrenBP : SuperBP
    {
        [DataMember]
        public ParentBP Parent { get; set; }
    }
</pre>
</div>
</p>
<p>Ustawienie znacznika IsReference na klasie ParentBP i pobranie referencji kończy się błędem:</p>
<p><img decoding="async" src="http://static.szogun1987.pl/pictures/WCFBlad2.png" alt="pictures/WCFBlad2.png"/></p>
<p>W większości przypadk&oacute;w należy postąpić zgodnie z komunikatem błędu i ustawić IsReference na klasie bazowej. Jeżeli jednak z jakiś powod&oacute;w nie chcemy tego robić możemy usunąć znacznik DataMember z pola Parent w klasie ChildrenBP i posiłkować się znacznikiem OnDeSerialized.</p>
<div class="code">
<pre class="prettyprint lang-cs">
    [KnownType(typeof(ChildrenBP))]
    [KnownType(typeof(ParentBP))]
    [DataContract]
    public class SuperBP
    {
        [DataMember]
        public string Name { get; set; }
    }
	
    [DataContract]
    public class ParentBP : SuperBP
    {
        [OnDeserialized]
        public void OnDeserialized(StreamingContext context)
        {
            foreach (ChildrenBP child in Childrens)
            {
                child.Parent = this;
            }
        }

        [DataMember]
        public List&lt;ChildrenBP&gt; Childrens { get; set; }
    }
	[DataContract]
    public class ChildrenBP : SuperBP
    {

        public ParentBP Parent { get; set; }
    }
</pre>
</div></p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/problem-zwrotnych-referencji-w-wcf/15/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Słów kilka o krotkach.</title>
		<link>https://szogun1987.pl/show/slow-kilka-o-krotkach-/14/</link>
					<comments>https://szogun1987.pl/show/slow-kilka-o-krotkach-/14/#comments</comments>
		
		<dc:creator><![CDATA[szogun1987]]></dc:creator>
		<pubDate>Sat, 09 Jul 2011 22:00:00 +0000</pubDate>
				<category><![CDATA[C Sharp]]></category>
		<category><![CDATA[Programowanie]]></category>
		<guid isPermaLink="false">https://szogun1987.pl/?p=14</guid>

					<description><![CDATA[Chciałem dzisiaj opisać trochę moje doświadczenia z krotkami.
Pomimo że ich konstrukcja nie jest złożona, a istnienie klasy o ich cechać było wyczekiwane dość długo to pojawiły]]></description>
										<content:encoded><![CDATA[<p>Chciałem dzisiaj opisać trochę moje doświadczenia z krotkami.</p>
<p>Pomimo że ich konstrukcja nie jest złożona, a istnienie klasy o ich cechać było wyczekiwane dość długo to pojawiły się one w .Net dopiero w wersji 4.0, a ich pojawienie się zostało zdecydowanie zagłuszone przez inne nowinki w tej wersji.</p>
</p>
<p>Pierwszym narzucającym się zastosowaniem dla krotek jest wielotypowana tablica. Tablica taka przydaje się gdy musimy przerzucić listę kilkuelementowych paczek obiekt&oacute;w pomiędzy dwoma miejscami w kodzie. Przykładem takiego miejsca wywoływanie operacji na bazie dla każdego rekordu zwr&oacute;conego przez obiekt implementujące IDataReader. Jak wiadomo przy pr&oacute;bie wywołania zapytania przed zamknięciem Readera następuje zgłoszenie wyjątku. Problem taki rozwiązywało się na kilka sposob&oacute;w (oczywiście nie polegających na rezygnowaniu z Readera):</p>
<p>1) Utworzenie kilku list dla każdego przepisywanego pola &#8211; powoduje konieczność stosowania pętli for zamiast foreach</p>
<p>2) Utworzenie listy tablic obiekt&oacute;w (listy słownik&oacute;w, lub innej wariacji generycznej) &#8211; fajne rozwiązanie dopuki nie potrzebna nam informacja o rzeczywistym typie elementu (wtedy trzeba rzutować).</p>
<p>3) Utworzenie klasy i przesyłanie listy obiekt&oacute;w tej klasy &#8211; C# to nie Java tutaj duża lisczba klas kuje w oczy ;]</p>
<p>4) Klasy anonimowe &#8211; byłyby idealne gdyby nie problem z nacechowaniem ich typem listy </p>
<p>5) Stosowanie elementu klasy stworzonej w innym celu (np. KeyValuePair&lt;T1, T2&gt;)</p>
</p>
<p>Zastosowanie krotek jest rozwiązaniem łączącym znaczną część zalet powyższych rozwiązań jednocześnie nie posiada większości ich wad:</p>
</p>
<div class="code">
<pre class="prettyprint lang-cs">
List&lt;Tuple&lt;int, string&gt;&gt; tempList = new List&lt;Tuple&lt;int, string&gt;&gt;();
using(SqlCommand cmd = new SqlCommand())
{
	cmd.Connection = con;
	cmd.CommandText = &quot;select id, nazwa from Tabela1&quot;;
	using(IDataReader reader = cmd.ExecuteReader())
	{
		while(reader.Read())
		{
			tempList.Add(new Tuple&lt;int, string&gt;());
		}
	}
}
using(SqlCommand cmd = new SqlCommand())
{
	cmd.Connection = con;
	cmd.CommandText = &quot;insert into Tabela2(id, nazwa) values (@id, @nazwa)&quot;;
	foreach(var tuple in tempList)
	{
		cmd.AddWithValue(&quot;@id&quot;, tuple.Item1);
		cmd.AddWithValue(&quot;@nazwa&quot;, tuple.Item2);
		cmd.ExecuteNonQuery();
	}
}
</pre>
</div>
</p>
<p>Inną ciekawostką związaną z krotkami jest fakt iż mają solidnie zaprogramowane funkcje GetHashCode i Equals, przez co można je wykorzystać żeby ułatwić sobie implementację tych metod:</p>
</p>
<div class="code">
<pre class="prettyprint lang-cs">
class ExampleClass
{
	public int IdPart1 { get; set; }
	public int IdPart2 { get; set; }

	public override int GetHashCode()
	{
		return new Tuple&lt;int, int&gt;(IdPart1, IdPart2).GetHashCode();
	}

	public override bool Equals(object obj)
	{
		if (obj is ExampleClass)
		{
			ExampleClass other = (ExampleClass)obj;
			return new Tuple&lt;int, int&gt;(IdPart1, IdPart2).Equals(new Tuple&lt;int, int&gt;(other.IdPart1, other.IdPart2));
		}
		return false;
	}
}
</pre>
</div>
</p>
<p>albo z wykorzystaniem <a href="http://szogun1987.ovh.org/index.php?id=7" target="_blank">LambdaEqualityComparer</a></p>
<div class="code">
<pre class="prettyprint lang-cs">
class ExampleClass
{
	public int IdPart1 { get; set; }
	public int IdPart2 { get; set; }

	private LambdaEqualityComparer&lt;ExampleClass, Tuple&lt;int, int&gt;&gt; comparer = 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new LambdaEqualityComparer&lt;ExampleClass, Tuple&lt;int, int&gt;&gt;(ec =&gt; new Tuple&lt;int, int&gt;(ec.IdPart1, ec.IdPart2));

	public override int GetHashCode()
	{
		return comparer.GetHashCode(this);
	}

	public override bool Equals(object obj)
	{
		return comparer.Equals(this, obj as ExampleClass);
	}
}
</pre>
</div>
</p>
<p>Krotki implementują też interfejs IComparable co może być przydatne jeżeli chcielibyśmy zaimplementować ten interfejs w swoich klasach (prawie klasyczny przykład Dekoratora).</p>
<p>Kolejnymi interfejsami implementowanymi przez Krotki są IStructuralEquatable i IStructuralComparable jest to związane z silnym wykorzystywaniem ich w języku F# (niestety jeszcze do niego nie przysiadłem). Więcej informacji na ten temat można uzyskać od Marcina Najdera z firmy Comarch kt&oacute;ry silnie promuje ten język na konferencjach.</p>
</p>
<p>Ze względu na fakt iż krotki po zainicjowaniu nie zmieniają swojego stanu mają podobno zastosowanie w aplikacjach wsp&oacute;łbieżnych (podobno bo sam nie miałem okazji się o tym przekonać).</p>
</p>
<p>Na koniec chciałbym dodać kilka sł&oacute;w o wykrytych przeze mnie niedopracowaniach krotek. </p>
<p>Pierwsza niedogodność Nazwy Item1, Item2, Item3&#8230; często uniemożliwiają domyślenie się co jest co, jednak po pierwsze nie mam innego pomysłu na nazwy tych właściwości, po drugie z założenia powinny być one wykorzystywane jako tymczasowe pojemniki na obiekty.</p>
<p>Druga fakt iż nie da się ich łatwo zserializować i deserializować (co też nie jest ich poprawnym zastosowaniem).</p>
</p>
<p>W komentarzach proszę o umieszczanie pomysł&oacute;w na inne zastosowanie dla krotek.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://szogun1987.pl/show/slow-kilka-o-krotkach-/14/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
