<?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>Sky.Log(); &#187; Programowanie</title>
	<atom:link href="http://blog.skyknight.info/category/programowanie/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.skyknight.info</link>
	<description></description>
	<lastBuildDate>Mon, 01 Mar 2010 20:47:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Niesforny statyczny konstruktor w C#</title>
		<link>http://blog.skyknight.info/2010/01/niesforny-statyczny-konstruktor-w-c/</link>
		<comments>http://blog.skyknight.info/2010/01/niesforny-statyczny-konstruktor-w-c/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 16:48:55 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://blog.skyknight.info/?p=167</guid>
		<description><![CDATA[Wpis bardziej &#8216;ku pamięci&#8217;, ale może komuś zaoszczędzić kłopotów ;-)
Załóżmy, że mamy taki oto kod:

    class First
    {
        static First()
        {
            Console.WriteLine(&#34;First static constructor&#34;);
 [...]]]></description>
			<content:encoded><![CDATA[<p>Wpis bardziej &#8216;ku pamięci&#8217;, ale może komuś zaoszczędzić kłopotów ;-)</p>
<p>Załóżmy, że mamy taki oto kod:</p>
<pre class="brush: csharp;">
    class First
    {
        static First()
        {
            Console.WriteLine(&quot;First static constructor&quot;);
        }

        public static void DoSth()
        {
            Console.WriteLine(&quot;Let's do sth&quot;);
        }
    }

    class Second : First
    {
        static Second()
        {
            Console.WriteLine(&quot;Second static constructor&quot;);
        }
    }
</pre>
<p>Jeśli wywołamy metodę <em>First.DoSth()</em> w outpucie otrzymamy:</p>
<p><code>First static constructor<br />
Let's do sth</code></p>
<p>Jeśli jednak spróbujemy z <em>Second.DoSth()</em> otrzymamy&#8230; to samo?! A gdzie wykonanie statycznego konstruktora klasy <em>Second</em>? Wszak w <a href="http://msdn.microsoft.com/en-us/library/k9x6w0hc%28VS.80%29.aspx">dokumentacji MSDN</a> możemy przeczytać:</p>
<blockquote><p>A static constructor is called automatically to initialize the class  before the first instance is created or any static members are referenced.</p></blockquote>
<p>I&#8230; to się zgadza! Podejrzyjmy<a href="http://www.red-gate.com/products/reflector/"> Reflectorem</a> jak kompilator zbudował aplikację:</p>
<p><a href="http://blog.skyknight.info/wp-content/uploads/2010/01/ref-sc.png"><img src="http://blog.skyknight.info/wp-content/uploads/2010/01/ref-sc.png" alt="" title="ref-sc" width="223" height="125" class="aligncenter size-full wp-image-168" /></a></p>
<p>W związku z tym, iż metoda <em>DoSth()</em> jest w klasie <em>First</em>, kompilator &#8216;olewa&#8217; nasze wywołanie przez klasę <em>Second</em>, przez co statyczny konstruktor tej drugiej się nie wykona. Jest to o tyle niebezpieczne (co sam w swoim kodzie &#8216;przetestowałem&#8217;), że jeśli metoda <em>DoSth()</em> jest w jakikolwiek sposób zależna od wyniku statycznego konstruktora (a wcześniej nic i nikt nie odwoływał się do <em>Second</em>), to możemy spędzić trochę czasu na szukaniu błędu&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2010/01/niesforny-statyczny-konstruktor-w-c/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>BlipTags</title>
		<link>http://blog.skyknight.info/2009/03/bliptags/</link>
		<comments>http://blog.skyknight.info/2009/03/bliptags/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 20:57:52 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[php mysql blip]]></category>

		<guid isPermaLink="false">http://blog.skyknight.info/?p=139</guid>
		<description><![CDATA[Cóż, Blip mi się jakoś spodobał ;-) Niestety, brakowało mi jednej funkcjonalności &#8211; jakiegoś centralnego miejsca ułatwiającego poruszanie się po tagach. Fakt, jest BlipCast, ale nie miał on chmury tagów ;-) Stąd też mając chwilę czasu w kilka godzin (choć na przestrzeni tygodnia) powstał skrypt umożliwiający przeglądanie tagów. Pokazuje on chmurki tagów, ich powiązania między [...]]]></description>
			<content:encoded><![CDATA[<p>Cóż, <a href="http://www.blip.pl">Blip</a> mi się jakoś spodobał ;-) Niestety, brakowało mi jednej funkcjonalności &#8211; jakiegoś centralnego miejsca ułatwiającego poruszanie się po tagach. Fakt, jest <a href="http://blipcast.pl/">BlipCast</a>, ale nie miał on chmury tagów ;-) Stąd też mając chwilę czasu w kilka godzin (choć na przestrzeni tygodnia) powstał skrypt umożliwiający przeglądanie tagów. Pokazuje on chmurki tagów, ich powiązania między sobą, otagowane zdjęcia oraz użytkowników-top-tagerów. </p>
<p><a href="http://skyknight.eu/bliptags">BlipTags</a></p>
<p>Jak na razie mój BlipBot bada wiadomości z przed kilku tygodni, dlatego też nowe statusy zostaną przejrzane później.</p>
<h3>Ale to brzydkie!</h3>
<p>Tak, wiem o tym doskonale. Są to niestety strzępy layoutu zrobionego kiedyś przez <a href="http://gecik.info">Geta</a> dla &#8216;portaluktóryjużistniećniebędzie&#8217; ;-) Designer ze mnie żaden, tak więc jeśli znalazłaby się jakaś dobra dusza, która poświęci swój jakże cenny czas i zaprojektuje jakiś prosty layout to będę bardzo wdzięczny :-)</p>
<h3>Błędy? Pomysły?</h3>
<p>Skrypt jest pełen błędów, niedoróbek i uproszczeń. Jeśli taką zauważyłeś lub coś Cię drażni albo masz jakiś inny pomysł &#8211; napisz w komentarzu, bądź na GG/<a href="http://skyknight.blip.pl">Blip</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2009/03/bliptags/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Klient REST w WCF</title>
		<link>http://blog.skyknight.info/2009/01/klient-rest-w-wcf/</link>
		<comments>http://blog.skyknight.info/2009/01/klient-rest-w-wcf/#comments</comments>
		<pubDate>Sat, 24 Jan 2009 20:49:30 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[csharp wcf tutorial]]></category>

		<guid isPermaLink="false">http://blog.skyknight.info/?p=111</guid>
		<description><![CDATA[Jak już się napisało, że kiedyś opiszę się tworzenie klienta RESTa w .Necie, to słowa trzeba dotrzymać. Postaram się jak najzwięźlej opisać w jak dość prosty sposób można otrzymać taką funkcjonalność. Przykładem będzie właśnie API dla Blipa, bowiem to przy nim &#8220;wypłynęło&#8221; kilka ciekawych zagadnień.

Na wstępie dla niewtajemniczonych:

REST
WCF
JSON

Całość opiera się na klasie WebChannelFactory, której to [...]]]></description>
			<content:encoded><![CDATA[<p>Jak już się napisało, że kiedyś opiszę się tworzenie klienta RESTa w .Necie, to słowa trzeba dotrzymać. Postaram się jak najzwięźlej opisać w jak dość prosty sposób można otrzymać taką funkcjonalność. Przykładem będzie właśnie <a href="http://www.blip.pl/api-0.02.html">API dla Blipa</a>, bowiem to przy nim &#8220;wypłynęło&#8221; kilka ciekawych zagadnień.<br />
<span id="more-111"></span><br />
Na wstępie dla niewtajemniczonych:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a></li>
<li><a href="http://en.wikipedia.org/wiki/Windows_Communication_Foundation">WCF</a></li>
<li><a href="http://en.wikipedia.org/wiki/Json">JSON</a></li>
</ul>
<p>Całość opiera się na klasie <a href="http://msdn.microsoft.com/en-us/library/bb908674.aspx">WebChannelFactory<T></a>, której to dostarczamy interface mapujący restowe operacje na metody. Jest to bardziej skonkretyzowana klasa względem <a href="http://msdn.microsoft.com/en-us/library/ms576132.aspx">ChannelFactory<T></a>, nastawiona na czysto webową komunikację. WebChannelFactory<T> potrafi także mapować odpowiedź serwera na odpowiednie klasy &#8211; obsługiwany jest zarówno XML jak i JSON. Myślę, że właśnie od owego mapowania warto zacząć pracę.</p>
<p>Blip na zapytanie dot. statusu odpowiada takim kodem:</p>
<pre class="brush: jscript;">
{
  'id': 1,
  'created_at': &quot;2007-10-18 11:27:20&quot;,
  'transport': {'id': 6, 'name': 'www'},
  'body': 'foobar http://rdir.pl/jk2hg',
  'type': 'Status',
  'user_path': '/users/frania',
  'pictures_path': '/updates/1/pictures',
  'recording_path': '/updates/1/recording',
  'movie_path': '/updates/12/movie'
}
</pre>
<p>Klasa w C# może wyglądać tak:</p>
<pre class="brush: csharp;">
    [DataContract]
    public class Update
    {
        [DataMember(Name=&quot;id&quot;)]
        public int Id { get; set; }

        [DataMember(Name=&quot;created_at&quot;)]
        public string CreatedAt { get; set; } 

        [DataMember(Name=&quot;transport&quot;)]
        public Transport Transport { get; set; }

        [DataMember(Name=&quot;body&quot;)]
        public string Body { get; set; }

        private UpdateTypes type;
        [DataMember(Name = &quot;type&quot;)]
        public string Type { get; set; }

        [DataMember(Name=&quot;user_path&quot;)]
        public string UserPath { get; set; }

        [DataMember(Name=&quot;recipient_path&quot;)]
        public string RecipientPath { get; set; }

        [DataMember(Name=&quot;pictures_path&quot;)]
        public string PicturesPath { get; set; }

        [DataMember(Name=&quot;recording_path&quot;)]
        public string RecordingPath { get; set; }

        [DataMember(Name=&quot;movie_path&quot;)]
        public string MoviePath { get; set; }
    }
</pre>
<p>Jak widać do wskazania klasy na którą odpowiedź ma być deserializowana używa się atrybuty <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx">DataContract</a>, natomiast dla wartości &#8211; <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx">DataMember</a> z opcjonalną właściwością Name. Według opisu API wartość type może mieć przyjmować tylko 4 wartości (Status, DirectMessage, PrivateMessage, Notice). Naturalne wydaje się być użycie enumeratora. <strong>Niestety</strong>, deserializer JSONa nie potrafi parsować ciągów znaków na enum &#8211; <a href="http://msdn.microsoft.com/en-us/library/bb412170.aspx">dozwolone są tylko wartości liczbowe</a>. Podobnie jest z datą &#8211; <strong>nie można</strong> w tym przykładzie dać typu DateTime właściwości CreatedAt, ponieważ odpowiedź ze strony serwera ma postać np. 2007-10-18 11:27:20, natomiast .Net wymaga Date([ilość ticków]). Problem można rozwiązać poprzez dopisanie właściwości/metod samodzielnie parsujących te dane.</p>
<p>Następnym krokiem jest utworzenie interface&#8217;u, który stanowić będzie &#8220;kontrakt&#8221; między klientem a serwerem. Tak jak dla klas danych, również i tutaj trzeba nadać odpowiedni atrybut &#8211; <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.aspx">ServiceContract</a>.</p>
<pre class="brush: csharp;">
    [ServiceContract]
    public interface IBlipApi
    {

    }
</pre>
<p>Do każdej z metod również musimy dodać atrybuty. Zawsze musi się pojawić <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.aspx">OperationContract</a> oraz drugi atrybut określający sposób komunikacji</p>
<pre class="brush: csharp;">
    public interface IBlipApi
    {
        [OperationContract]
        [WebGet(UriTemplate = &quot;/updates/{id}&quot;, ResponseFormat = WebMessageFormat.Json)]
        Update GetUpdate(string id);

        [OperationContract]
        [WebInvoke(UriTemplate = &quot;/updates?update[body]={body}&quot;, Method = &quot;POST&quot;]
        void CreateUpdate(string body);

        [OperationContract]
        [WebInvoke(UriTemplate = &quot;/updates/{id}&quot;, Method=&quot;DELETE&quot;)]
        void RemoveUpdate(string id);
    }
</pre>
<p><a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.aspx">WebGet</a> jest de facto atrybutem <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webinvokeattribute.aspx">WebInvoke</a> z ustawioną metodą GET. W parametrze UriTemplate podajemy ścieżkę (bez adresu serwera &#8211; o tym później) zapytania. W nawiasach klamrowych pojawią się wartości z parametrów przekazanych do metody. Niestety, owe parametry mogą być <strong>tylko</strong> typu string (nie wiem czemu przy innych typach nie może być wywoływana metoda ToString()). W metodach zwracających dane trzeba jeszcze określić jakiego są one typu &#8211; domyślnie XML.</p>
<p>Tak gotowy interface trzeba przekazać fabryce.</p>
<pre class="brush: csharp;">
            WebChannelFactory&lt;IBlipApi&gt; channelFactory = new WebChannelFactory&lt;IBlipApi&gt;(new WebHttpBinding(), new Uri(&quot;http://api.blip.pl&quot;));
            IBlipApi api = channelFactory.CreateChannel();
</pre>
<p>W teorii byłoby to na tyle. <strong>Ale jest &#8216;ale&#8217;</strong> ;-) API Blipa (tak jak pewnie wiele innych) potrzebuje w nagłówku żądania dwóch parametrów: <em>Accept: application/json</em> oraz <em>X-Blip-API: 0.02</em>. Nie znalazłem innego rozwiązania jak skorzystać z <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontextscope.aspx">kontekstu</a> i ustawienia w nim odpowiednich nagłowków</p>
<pre class="brush: csharp;">
            WebChannelFactory&lt;IBlipApi&gt; channelFactory = new WebChannelFactory&lt;IBlipApi&gt;(new WebHttpBinding(), new Uri(&quot;http://api.blip.pl&quot;));
            IBlipApi api = channelFactory.CreateChannel();
            using(OperationContextScope context = new OperationContextScope((IContextChannel)api))
            {
             WebOperationContext.Current.OutgoingRequest.Accept = &quot;application/json&quot;;
             WebOperationContext.Current.OutgoingRequest.Headers.Add(&quot;X-Blip-API&quot;, &quot;0.02&quot;);
             WebOperationContext.Current.OutgoingRequest.Headers.Add(&quot;Authorization&quot;, string.Format(&quot;Basic {0}&quot;,
                EncodeTo64(string.Format(&quot;{0}:{1}&quot;, user, password))));
                                    Console.WriteLine(api.GetUpdate(&quot;555&quot;).Body);
            }
</pre>
<p>W powyższym przykładzie dodałem jeszcze w nagłówku dane do autoryzacji w serwisie. Drugim &#8220;ale&#8221; jest odpowiedź z serwera Blip &#8211; .Net spodziewa się otrzymać Content-Type: application/json, tymczasem dostaje text/js przez co <strong>wyrzuca wyjątkiem</strong>. Najlepiej byłoby móc ustawić, iż zawsze z tego serwera otrzymujemy dane w postaci JSONa. W tym celu musimy utworzyć własny obiekt <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding.aspx">Binding()</a> i przekazać mu inny obiekt z metodą informującą o tym, że zwrócone przez serwer dane to obsługiwany format. Brzmi zawile ale kod powinien to wyjaśnić. Najpierw tworzymy klasę dziedziczącą po WebContentTypeMapper.</p>
<pre class="brush: csharp;">
    internal class BlipMapper : WebContentTypeMapper
    {
        public override WebContentFormat GetMessageFormatForContentType(string contentType)
        {
            return WebContentFormat.Json;
        }
    }
</pre>
<p>Czego byśmy nie dostali w odpowiedzi traktujemy to zawsze jako JSON. Oczywiście, bardziej ambitni mogą zacząć tutaj odpowiednio sprawdzać przychodzącą wartość. Następnie definiujemy taką metodę:</p>
<pre class="brush: csharp;">
        private Binding GetBinding()
        {
            CustomBinding binding = new CustomBinding(new WebHttpBinding());
            WebMessageEncodingBindingElement element = binding.Elements.Find&lt;WebMessageEncodingBindingElement&gt;();
            element.ContentTypeMapper = new BlipMapper();
            return binding;
        }
</pre>
<p>Tworzy ona nasz własny obiekt Binding() i dodaje do niego wcześniej zdefiniowanego mappera. Trzeba jeszcze tylko zmodyfikować jedną linię:</p>
<pre class="brush: csharp;">
            WebChannelFactory&lt;IBlipApi&gt; channelFactory = new WebChannelFactory&lt;IBlipApi&gt;(GetBinding(), new Uri(&quot;http://api.blip.pl&quot;));
</pre>
<p><em>Voila!</em></p>
<p>Jak widać utworzenie klienta REST w .Necie 3.5 nie jest trudne &#8211; większość operacji przejmuje na siebie WCF. Jednak <strong>nie ma róży bez kolców</strong> &#8211; nie wszystkie typy danych łatwo się mapują, przekazywane w parametrach wartości muszą być stringami i nie ma żadnego mechanizmu ich sprawdzania. Także zabawa z kontekstami przy ich dużej ilości może być kłopotliwa.</p>
<p>Ten wpis nie powstał &#8220;znikąd&#8221;. Pomogły następujące strony:</p>
<ul>
<li><a href="http://blogs.msdn.com/carlosfigueira/">Carlo&#8217;s blog</a> &#8211; kilka przykładów użycia WCF</li>
<li><a href="http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/bf7eda10-3930-4999-8f9e-b3be5ae8f2f3/">dyskusja nt. dostępu do nagłówków HTTP</a></li>
<li><a href="http://jeffbarnes.net/portal/blogs/jeff_barnes/archive/2007/11/28/wcf-3-5-webinvoke-attribute.aspx">użycie atrybutu WebInvoke</a></li>
<li><a href="http://blogs.msdn.com/bags/archive/2008/06/10/rest-in-wcf-part-v-hi-rest-exposing-a-service-via-get-the-servicecontract-and-implementation.aspx">kurs REST i WCF</a> (linki do poprzednich części w treści wpisu)</li>
<li><a href="http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/40a32404-e921-42d9-86c0-f399726de0b4/">dyskusja WCF i JSON</a></li>
</ul>
<p>Dzięki!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2009/01/klient-rest-w-wcf/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WCF + Blip = WcfBlip</title>
		<link>http://blog.skyknight.info/2009/01/wcf-blip-wcfblip/</link>
		<comments>http://blog.skyknight.info/2009/01/wcf-blip-wcfblip/#comments</comments>
		<pubDate>Tue, 20 Jan 2009 19:28:27 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[wcf csharp blip library]]></category>

		<guid isPermaLink="false">http://blog.skyknight.info/?p=97</guid>
		<description><![CDATA[Wyszło jak zawsze &#8211; przypadkiem. Wśród napisanych blipowych bibliotek znalazła się jedna dla .neta. Niestety, nie jest już rozwijana w związku z czym spróbowałem napisać swoją. Po kilku godzinach surfowania w Sieci udało mi się zdobyć na tyle dużo wiedzy nt. WCF by to właśnie w tej technologi wykonać bibliotekę. I myślę, że udało się, [...]]]></description>
			<content:encoded><![CDATA[<p>Wyszło jak zawsze &#8211; przypadkiem. Wśród napisanych <a href="http://blip.wikidot.com/aplikacje">blipowych bibliotek</a> znalazła się jedna dla <a href="http://sourceforge.net/projects/sharpbliplib">.neta</a>. Niestety, nie jest już rozwijana w związku z czym spróbowałem napisać swoją. Po kilku godzinach surfowania w Sieci udało mi się zdobyć na tyle dużo wiedzy nt. <acronym title="Windows Communication Foundation">WCF</acronym> by to właśnie w tej technologi wykonać bibliotekę. I myślę, że udało się, choć nie cała funkcjonalność API Blipa się w niej znajduje. </p>
<p><strong>Pliki</strong><br />
<a href="http://blog.skyknight.info/wp-content/uploads/2009/01/wcfblip.zip">kod źródłowy (Visual Studio 2008)</a><br />
<strong>UPDATE</strong> [01.01.2010]<br />
<a href="http://github.com/SkyKnight/WcfBlip">projekt na GitHub</a></p>
<p><strong>Wymagania</strong><br />
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=333325FD-AE52-4E35-B531-508D977D32A6&#038;displaylang=en">.Net Framework 3.5</a></p>
<p><strong>Użycie</strong></p>
<p>Generalnie wszystkie wywołania metod znajdują się we właściwości <em>Api</em> klasy <em>Blip</em>. Jest tak dlatego, że podczas pobierania owej właściwości tworzony jest kontekst z wymaganymi przez API nagłówkami HTTP. Jeśli aplikacja, która piszesz łączy się z innymi źródłami danych przez HTTP, warto dla bezpieczeństwa wywoływać metodę Blip.Dispose() lub używać klauzuli using(), by usunąć kontekst.</p>
<p>Parametry przekazywane do wywołań niestety mogą być tylko typu string (<del datetime="2009-02-18T18:43:14+00:00">wymóg WCF</del>  <strong>UPDATE</strong>: cóż, w innym kontekście może i można, ale ja dostaje wyjątek) i nie są w żaden sposób sprawdzane.</p>
<p>            using (WcfBlip.Blip blip = new WcfBlip.Blip(&#8220;uzytkownik&#8221;, &#8220;haslo&#8221;)) // logujemy się<br />
            {<br />
                Updates[] updates = blip.Api.GetUpdates(); // pobiera ostatnie statusy użytkownika<br />
                Updates[] updates2 = blip.Api.GetUpdates(&#8220;10&#8243;, &#8220;5&#8243;); // pobiera 10 ostatnich statusów zaczynając od 5<br />
                User user = blip.Api.GetUser(&#8220;jack&#8221;); // pobiera dane nt. użytkownika &#8220;jack&#8221;<br />
            }</p>
<p>Trochę więcej przykładów znajduje się <em>WcfBlipTest</em></p>
<p>Choć według <a href="http://www.blip.pl/api-0.02.html">opisu API</a> jest podział na update&#8217;y, statusy, prywatne wiadomości i uwagi, to zdecydowałem się na jedną klasę Update, która to posiada właściwość Type, po której to można rozpoznawać typ wiadomości.</p>
<p><strong>Do poprawki</strong></p>
<ul>
<li>uzupełnić brakujące metody (upload obrazków, avatarów, backgroundów)</li>
<li>dodać komentarze do kodu</li>
<li>dodać do klas encji właściwości zwracające nazwy użytkowników (a nie jak teraz &#8211; tylko ich URL)</li>
<li>wprowadzić obsługę błędów (na razie nie ma żadnej)</li>
</ul>
<p><strong>Licencja</strong><br />
<a href="http://www.opensource.org/licenses/mit-license.php">MIT</a></p>
<p>Wszelkie komentarze i uwagi mile widziane :-)</p>
<p>P.S. W najbliższym czasie postaram się napisać o tworzeniu klientów REST w .Necie za pomocą WCF.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2009/01/wcf-blip-wcfblip/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Własny widget dla Wordpressa</title>
		<link>http://blog.skyknight.info/2009/01/wlasny-widget-dla-wordpressa/</link>
		<comments>http://blog.skyknight.info/2009/01/wlasny-widget-dla-wordpressa/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 21:10:19 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[php wordpress widget plugin]]></category>

		<guid isPermaLink="false">http://blog.skyknight.info/?p=93</guid>
		<description><![CDATA[Wordpressowy sidebar bardzo mi się podoba &#8211; nie muszę grzebać w kodzie, by coś poprzesuwać, zmieniać. Jednak zanim napiszesz własny prosty widget, pamiętaj, jest jeden mały &#8220;myk&#8221; ;-) W dokumentacji Widget API napisano, że aby zarejestrować nowy widget należy wywołać (np. w pluginie) register_sidebar_widget(). Szkoda tylko, że ktoś nie wspomniał o tym, że w najnowszych [...]]]></description>
			<content:encoded><![CDATA[<p>Wordpressowy sidebar bardzo mi się podoba &#8211; nie muszę grzebać w kodzie, by coś poprzesuwać, zmieniać. Jednak zanim napiszesz własny prosty widget, pamiętaj, jest jeden mały &#8220;myk&#8221; ;-) W dokumentacji Widget API <a href="http://codex.wordpress.org/Plugins/WordPress_Widgets_Api">napisano</a>, że aby zarejestrować nowy widget należy wywołać (np. w pluginie) <a href="http://codex.wordpress.org/WordPress_Widgets_Api/register_sidebar_widget">register_sidebar_widget()</a>. Szkoda tylko, że ktoś nie wspomniał o tym, że w najnowszych wersjach WP (bodajże od 2.5.x) ta funkcja dołączana jest przez core Wordpressa później niż plugin w związku z tym otrzymujemy piękny komunikat:</p>
<p><code>Call to undefined function: register_sidebar_widget</code></p>
<p>&#8220;Szybkie&#8221; rozwiązanie zostało przedstawione <a href="http://www.linickx.com/archives/401/call-to-undefined-function-register_sidebar_widget">w tym poście</a>, chociaż wydaję mi się trochę błędne, stąd też sadzę, że ten kod jest lepszy:</p>
<p> function widget_becool ($args) {<br />
	echo $args['before_widget'];<br />
	echo $args['before_title'];<br />
	echo &#8216;Becool!&#8217;;<br />
	echo $args['after_title'];<br />
	// sth<br />
	echo $args['after_widget'];<br />
}</p>
<p>function widget_init_becool() {<br />
	register_sidebar_widget( &#8216;Becool&#8217;, &#8216;widget_becool&#8217; );<br />
}<br />
add_action(&#8216;widgets_init&#8217;, &#8216;widget_init_becool&#8217;);</p>
<p>Można użyć <a href="http://pl2.php.net/manual/en/function.create-function.php">create_function()</a>, ale myślę, że tak jest czytelniej :-)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2009/01/wlasny-widget-dla-wordpressa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mp3Arranger</title>
		<link>http://blog.skyknight.info/2008/12/mp3arranger/</link>
		<comments>http://blog.skyknight.info/2008/12/mp3arranger/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 20:54:22 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[c# music mp3]]></category>

		<guid isPermaLink="false">http://blog.skyknight.info/?p=75</guid>
		<description><![CDATA[Przetrząsając swój dysk w poszukiwaniu zaginionych plików muzycznych, zachciało mi się programu, który to zrobiłby porządek w katalogach układając je wg nazwy artysty i albumu. Nie doszukałem się takiej funkcjonalności w Winampie, a w Googlach nawet nie szukałem. W ramach poświątecznego ruszania mózgiem postanowiłem napisać sobie coś takiego samemu. Wybór padł oczywiście na C#.
Założenie było [...]]]></description>
			<content:encoded><![CDATA[<p>Przetrząsając swój dysk w poszukiwaniu zaginionych plików muzycznych, zachciało mi się programu, który to zrobiłby porządek w katalogach układając je wg nazwy artysty i albumu. Nie doszukałem się takiej funkcjonalności w Winampie, a w Googlach nawet nie szukałem. W ramach poświątecznego ruszania mózgiem postanowiłem napisać sobie coś takiego samemu. Wybór padł oczywiście na C#.</p>
<p>Założenie było proste: na podstawie tagów w plikach muzycznych program ma pozakładać katalogi z nazwą artysty i podkatalogi z nazwami albumów oraz przenieść tam pliki.</p>
<p>Na oficjalnej stronie <a href="http://id3.org">ID3</a> znalazłem odpowiednie <a href="http://id3.org/Implementations">implementacje dla C#</a>. Wybrałem <a href="http://developer.novell.com/wiki/index.php/TagLib_Sharp">TagLib#</a> ponieważ obsługiwał nie tylko Mp3, ale również Ogg i WMA (oraz jeszcze kilka innych formatów, których nawet nie używam). <strong>I tu chciałem zamieścić krótką informację.</strong>  Skompilowana dll&#8217;ka, która jest tam dostępna ma problemy z innymi formatami niż mp3 &#8211; należy pobrać najświeższy kod z <a href="svn://anonsvn.mono-project.com/source/trunk/taglib-sharp">ichniego svna</a>, wtedy wszystko działa.</p>
<p>Pliki:</p>
<ul>
<li><a href="http://blog.skyknight.info/wp-content/uploads/2008/12/mp3arranger.zip">Skompilowany program</a></li>
<li><a href="http://blog.skyknight.info/wp-content/uploads/2008/12/mp3arranger1.zip">Kod źródłowy</a></li>
</ul>
<p><strong>Wymagany jest <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=333325FD-AE52-4E35-B531-508D977D32A6&#038;displaylang=en">.Net 3.5</a></strong> (nie chciało mi się zmieniać projektu na dwójkę&#8230; ;-) )</p>
<p>Features:</p>
<ul>
<li>obsługa Mp3, Ogg i WMA</li>
<li>możliwość wprowadzenia własnych wzorców nazw katalogów</li>
<li>ubogi design ;-)</li>
</ul>
<p>Known bugs:</p>
<ul>
<li>niestety, TagLib# ma problemy z polskimi literami w tagach ID3v1 &#8211; rozwiązaniem jest używanie tylko IDv2 lub przymknięcie oka na &#8220;krzaczki&#8221; w nazwach katalogów ;-)</li>
</ul>
<p>Licencja: <a href="http://sam.zoy.org/wtfpl/">WTFPL</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2008/12/mp3arranger/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Statyczny konstruktor w PHP</title>
		<link>http://blog.skyknight.info/2008/09/statyczny-konstruktor-w-php/</link>
		<comments>http://blog.skyknight.info/2008/09/statyczny-konstruktor-w-php/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 16:43:28 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.skyknight.info/?p=39</guid>
		<description><![CDATA[W C# istnieje możliwość utworzenia statycznego konstruktora, który jest uruchamiany przy pierwszym odwołaniu do danej klasy. Wygląda to mniej więcej tak:
    public class Foo
    {
        static Foo()
        {
        [...]]]></description>
			<content:encoded><![CDATA[<p>W C# istnieje możliwość utworzenia <a href="http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx">statycznego konstruktora</a>, który jest uruchamiany przy pierwszym odwołaniu do danej klasy. Wygląda to mniej więcej tak:</p>
<p>    public class Foo<br />
    {<br />
        static Foo()<br />
        {<br />
            System.Diagnostics.Trace.Write(&#8220;Klasa Foo zostala zaladowana&#8221;);<br />
        }<br />
    }</p>
<p>Zdarza się, że podobna funkcjonalność przydałaby się w PHP, który jednak tej konstrukcji nie obsługuje. Można to jednak w prosty sposób &#8220;zasymulować&#8221; poprzez odpowiednie zmodyfikowanie &#8220;magicznej&#8221; funkcji <a href="http://pl2.php.net/autoload">__autoload()</a> oraz dodanie statycznej metody do klasy, która będzie udawać konstruktora (w moim przykładzie użyłem nazwy <em>staticConstruct</em>).</p>
<p>class Foo<br />
{<br />
	public function __construct()<br />
	{<br />
		// &#8216;normalny&#8217; konstruktor<br />
	}</p>
<p>	public static function staticConstruct()<br />
	{<br />
		echo &#8216;Klasa Foo zostala zaladowana&#8217;;<br />
	}<br />
}</p>
<p>function __autoload($className)<br />
{<br />
	// obsluga zaladowania klasy<br />
	// &#8230;<br />
	// &#8230;</p>
<p>	if(is_callable(array($className, &#8217;staticConstruct&#8217;)))<br />
	{<br />
		call_user_func(array($className, &#8217;staticConstruct&#8217;));<br />
	}<br />
}</p>
<p>Jak widać sposób implementacji jest wręcz trywialny. Niemniej pojawia się dwie kwestii, które trzeba wyjaśnić:</p>
<ul>
<li>statyczny konstruktor jest publiczny przez co można wywoływać go w kodzie &#8211; można ten problem rozwiązać poprzez wprowadzenie odpowiedniego statycznego pola typu boolean, które będzie sprawdzane przez owy konstruktor &#8211; nie jest to do końca &#8220;eleganckie&#8221; rozwiązanie, niemniej innego sposobu nie dostrzegłem</li>
<li>statyczny konstruktor w klasie dziedziczącej <strong>nie musi</strong> (i nie jest to nawet wskazane) wcale wywoływać konstruktora z klasy nadrzędnej, bowiem zostanie on samodzielnie wywołany przez __autoload() w czasie ładowania klasy</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2008/09/statyczny-konstruktor-w-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dragonfly alpha</title>
		<link>http://blog.skyknight.info/2008/05/dragonfly-alpha/</link>
		<comments>http://blog.skyknight.info/2008/05/dragonfly-alpha/#comments</comments>
		<pubDate>Wed, 07 May 2008 18:21:51 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.skyknight.info/2008/05/07/dragonfly-alpha/</guid>
		<description><![CDATA[Firebug jest jednym z najlepszych pluginów dla Firefoksa &#8211; jeśli nie w rankingu ogólnym, to na pewno ma uznanie wśród osób tworzących witryny. Dla IE powstał trochę ubogi (jak sama przeglądarka) Developer Toolbar, jednak brakowało jakiś porządniejszych narzędzi dla Opery.

Od kilku dni sytuacja się trochę zmieniła. Po szumnych zapowiedziach w końcu mamy wersję alpha nowego [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://getfirebug.com/">Firebug</a> jest jednym z najlepszych pluginów dla Firefoksa &#8211; jeśli nie w rankingu ogólnym, to na pewno ma uznanie wśród osób tworzących witryny. Dla IE powstał trochę ubogi (jak sama przeglądarka) <a href="http://www.microsoft.com/downloadS/details.aspx?familyid=E59C3964-672D-4511-BB3E-2D5E1DB91038&#038;displaylang=en">Developer Toolbar</a>, jednak brakowało jakiś porządniejszych narzędzi dla Opery.</p>
<p><a href='http://blog.skyknight.info/wp-content/uploads/2008/05/dragonfly.jpg' title='Dragonfly'><img src='http://blog.skyknight.info/wp-content/uploads/2008/05/dragonfly.thumbnail.jpg' alt='Dragonfly' /></a></p>
<p>Od kilku dni sytuacja się trochę zmieniła. Po szumnych zapowiedziach w końcu mamy <a href="http://my.opera.com/desktopteam/blog/2008/05/06/getting-ready-for-dragonfly">wersję alpha</a> nowego dodatku dla owej przeglądarki &#8211; <a href="http://www.opera.com/products/dragonfly/">Dragonfly</a>. Napisany w JavaScripcie i uruchamiany jako dodatkowe okno jest jednak trochę &#8216;przereklamowany&#8217;. Oczywiście zdaję sobie sprawę, że nie jest to wersja finalna i dużo się jeszcze zmieni, jednak liczyłem na &#8216;trochę więcej&#8217;. Czego mi brakuje?</p>
<ul>
<li>większej integracji z samą przeglądarką &#8211; coś w stylu opcji &#8216;Inspect element&#8217; w menu kontekstowym w Firefoksie+Firebug</li>
<li><strong>edytowanie &#8216;na gorąco&#8217; atrybutów elementów oraz arkuszy stylów</strong></li>
<li>podglądanie wysyłanych/odbieranych danych (nagłówki HTTP, dane typu POST, żądania AJAX)</li>
</ul>
<p>Jeśli powyższe punkty trafią do wersji finalnej, to myślę, że Dragonfly zostanie dobrym konkurentem dla Firebuga :-)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2008/05/dragonfly-alpha/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>spotBox</title>
		<link>http://blog.skyknight.info/2008/03/spotbox/</link>
		<comments>http://blog.skyknight.info/2008/03/spotbox/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 19:58:09 +0000</pubDate>
		<dc:creator>SkyKnight</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://skyknight.info/blog/2008/03/26/spotbox/</guid>
		<description><![CDATA[Korzystając z wolnego czasu oraz na prośbę szefa Playbacku, napisałem prosty skrypt wyświetlający w formie slajdów dowolną treść (boks &#8220;Gorące informacje&#8221; na gram.pl, czy oferta na polskiej stronie EA), zwany ponoć spotem. Skrypt korzysta z frameworka Script.aculo.us i choć jest prosty w swojej budowie, to jednak zdecydowałem się go opublikować, bo może nie tylko ja [...]]]></description>
			<content:encoded><![CDATA[<p>Korzystając z wolnego czasu oraz na prośbę szefa <a href="http://www.playback.pl">Playbacku</a>, napisałem prosty skrypt wyświetlający w formie slajdów dowolną treść (boks &#8220;Gorące informacje&#8221; na <a href="http://gram.pl">gram.pl</a>, czy oferta na <a href="http://www.polska.ea.com/">polskiej stronie EA</a>), zwany ponoć spotem. Skrypt korzysta z frameworka <a href="http://script.aculo.us">Script.aculo.us</a> i choć jest prosty w swojej budowie, to jednak zdecydowałem się go opublikować, bo może nie tylko ja z niego będę korzystał ;-) <strong><a href="http://skyknight.info/projects/spotbox/">zobacz demo »</a></strong></p>
<p><span id="more-30"></span></p>
<ul class="download">
<li><a href="http://script.aculo.us/downloads">script.aculo.us</a> &#8211; framework niezbędny do działania skryptu</li>
<li><a href="http://skyknight.info/projects/spotbox/spotbox-0.1-full.zip">spotBox 0.1 Full</a> &#8211; paczka zawierająca prócz spotBoxa także niezbędne moduły script.aculo.us w wersji 1.8.1</li>
<li><a href="http://skyknight.info/projects/spotbox/js/spot.js">spotBox 0.1</a> &#8211; &#8220;czysty&#8221; skrypt spotBox</li>
</ul>
<p>Instalacja jest banalnie prosta. Wystarczy dodać następujące wpisy w sekcji head:</p>
<p>      <script type="text/javascript" src="twojkatalogjs/prototype.js"></script><br />
      <script type="text/javascript" src="twojkatalogjs/scriptaculous.js?load=effects"></script><br />
      <script type="text/javascript" src="twojkatalogjs/spot.js"></script></p>
<p>a w części treści:</p>
<div id="spotbox">
<div class="spotitem" style="display:block;">
			<!-- tresc 1-go panelu -->
		</div>
<div class="spotitem" style="display:none;">
			<!-- tresc 2-go panelu-->
		</div>
<p>		<!-- więcej paneli ;-)</p>
<p>		...</p>
<p>		-->
	</p></div>
<ul>
<li>pierwszy element nie musi mieć ustawionego parametru <code>display</code> na <code>block</code> &#8211; skrypt automatycznie nada mu taką wartość</li>
<li>skrypt samodzielnie utworzy listę z numerami paneli (ul), w której to aktualna strona ma klasę <code>current</code></li>
</ul>
<p>Wszelkie uwagi i konstruktywna krytyka mile widziane :-)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.skyknight.info/2008/03/spotbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
