Tags: , , , , , , , | Categories: .Net Posted by karol.ch on 4/1/2009 3:30 PM | Comments (1)
Ten wpis jest tłumaczeniem części artykułu pt. "MVP-Submitted: Calculating with Infinite Sequences in C#" zamieszczonego na stronach Visual C# Developer Center. Powstało ono jako część zaliczenia jednego z przedmiotów na studiach. Początkowo nie miałem zamiaru upubliczniać tej pracy. Dlaczego? Ponieważ to tłumaczenie nie kładzie nacisku na ściśle techniczny język. Starałm się raczej uchwycić główną ideę przekazywanych myśli i pisać tak, aby zrozumiał laik :).

Zmotywował mnie jeden z kolegów, chociaż muszę przyznać, że nie bez znaczenia był też e-mail od Tomasa: "I'd definitely love to see a link to the translated article once it is published!".

Chętnie przetłumaczę koleją część - jeśli zaleje mnie fala e-maili mówiących o takiej potrzebie :). Jeśli chcesz umieścić tę treść na swojej stronie WWW, proszę najpierw o kontakt ze mną.

 Dodane przez MVP: Wykonywanie obliczeń z nieskończonymi sekwencjami w C#

 

Autor: Tomas Petricek.

Tłumaczenie: Karol Chęciński

 

Mój poprzedni artykuł traktował o opóźnionym wykonywaniu i skupiał się na tym jak się je symuluje w C#. Zaimplementowaliśmy klasę Lazy<T>, która reprezentuje wartość obliczaną na żądanie –oznacza to, że klasa „wie” jak obliczyć wartość wyrażenia, ale nie robi tego dopóki faktycznie nie jest ona potrzebna w programie. Bardzo interesującą strukturą danych, znaną z programowania funkcjonalnego, którą można zaimplementować używając tej opóźnionej komórki jest opóźniona lista. Każdy element tej listy zawiera wartość związaną numerem (na przykład liczbę) i wie jak przeliczyć następny element na liście, ale jest opóźniony co oznacza, że kolejny element nie zostanie obliczony, dopóki program nie odwoła się do jego wartości. Najbardziej interesującym aspektem opóźnionych list  jest to, że mogą by użyte do reprezentowania sekwencji nieskończonych – jest to możliwe ponieważ elementy są przeliczane tylko jeśli są potrzebne i dlatego lista zawsze będzie zawierać tylko skończoną liczbę elementów i ciągle będzie mogła przeliczać kolejne jeśli będzie to konieczne.

                 W tym artykule pokażę, że opóźnioną listę można zaimplementować używając typu IEnumerable<T>, a także zademonstruję jak operacje na zapytaniach LINQ mogą być użyte do manipulowania nieskończoną listą. Ostatecznie spojrzymy na implementacje sekwencji Mandelbrota (widać go na obrazku obok) używając technik opisanych w tym artykule.

 

Wprowadzenie do IEnumerable.

 

                Większość z Was najpewniej wie, że sekwencje w .NET można reprezentować używając interfejsu IEnumerable<T>. Można go użyć do enumerowania jednostek w standardowych kolekcjach takich jak tablice, listy, słowniki oraz w specjalnych kolekcjach. Tego interfejsu używa się często razem z pętlą foreach. Przejrzyjmy najpierw metody tego interfejsu. (Inne metody takie jak te dziedziczone po IDisposable nie są ważne dla naszego przykładu):

 

interface IEnumerable<T> : IDisposable<T>
{
  public void Reset();
  public bool MoveNext();
  public T Current { get; }
  // ... other methods omitted ...
}

 

                Enumerowanie w strukturze danych robi się używając trzech metod pokazanych w poprzednim przykładzie kodu. Najpierw wywoływana jest metoda Reset aby przesunąć wskaźnik enumeratora przed pierwszy element. Potem metoda MoveNext przesuwa enumerator do następnego elementu w sekwencji albo zwraca fałsz jeśli nie ma więcej elementów. Podczas enumeracji można dostać się do wybranego elementu używając właściwości Current.

 

class MyList {
  int[] elements;
  IEnumerabl<int> GetEnumerable() {
    for(int i=0; i<elements.Length; i++)
      yield return elements[i];
  }
}


                Przed wersją 2.0 C#, trzeba było zaimplementować ten interfejs gdy chciało się pozwolić na enumerację własnej kolekcji danych. To wprowadzało niepotrzebne skomplikowanie, więc w C# 2.0 wprowadzono zwracanie wartości yield. Używając tego słowa kluczowego, implementacja własnego numeratora jest tak łatwa jak iterowanie po wszystkich elementach w pętli. Spójrzmy bardzo prosty przykład:

 

var en = myList.GetEnumerable(); 

 

                Ta klasa pokazuje jak metoda która zwraca implementację IEnumerable<T> może być używana do enumerowania wszystkich elementów w tablicy. Ciało tej metody nie zwraca bezpośredniej implementacji interfejsu - zamiast tego używa zwracania yield, które jest kompilowane do implementacji interfejsu przez kompilator C#. Zrozumienie czym jest ten kod jest łatwe (po prostu iteruje po wszystkich elementach i zwraca każdy element oddzielnie z tablicy używając yield), ale wyjaśnienie jak ten kod jest używany do implementacji interfejsu IEnumerable<T> wymagałoby kolejnego artykułu. Ważną rzeczą do zrozumienia jest to co się dzieje podczas wywoływania metody zaimplementowanej przy pomocy zwracania yield jak w przykładzie poniżej:

                Kiedy wykonuje się to wywołanie, obiekt generowany przez kompilator jest tworzony, ale ani jedna linia (z napisanego przez ciebie kodu) nie jest realizowana! Realizacja kodu zaczyna się po użyciu metody MoveNext. Wchodzi ona do pierwszego wystąpienia zwracania yield a następnie „porzuca” metodę, a kontrola jest przekazywana z powrotem do metody wzywającej metodę MoveNext. Oczywiście nie jest możliwe wyjście z realizowanej metody i ponowne „wskoczenie” (utrzymywanie oryginalnych stanów zmiennych w metodzie), więc kompilator musi przetłumaczyć kod w metodzie na klasę, podnieść rangę zmiennych i skonwertować na właściwości klasy oraz wygenerować kod implementujący przejście między każdym użyciem zwracania yield. Kompilator C# tłumaczy kod metody na stan maszynowy gdzie każde użycie zwracania yield odpowiada pojedynczemu stanowi.

Nieskończone sekwencje i operacje na zapytaniach LINQ


                Najważniejszą rzeczą jaką chciałem uwypuklić w poprzedniej części jest to, że całe ciało metody nie jest realizowane dopóki nadrzędna metoda powtarzająco wykonująca MoveNext nie dojdzie do końca (i zwróci fałsz). To oznacza, że jeśli napiszemy kod, który wykonywał by się bez końca, ale zawrzemy wywołanie zwracania yield wewnątrz tego kodu, nie spowodujemy pętli nieskończonej. Spójrzmy na najprostszy z możliwych przykład:

 

IEnumerable<int> GetNumbers()
{
  int i = 0;
  while(true) yield return i++;
}

// Create an infinite sequence of integers
var nums = GetNumbers();


                Metoda GetNumbers w prezentowanym kodzie zwraca implementację IEnumerable<int>, która może być używana do przechodzenia w pętli po wszystkich typach liczbowych zaczynając od 0. Ponieważ typ liczbowy ma ograniczony zasięg, wartości zostaną przeładowane, a enumerowanie zacznie się znowu od Int32.MinValue.

                W powyższym przykładzie używamy tej metody do stworzenia zmiennej nums. Jej wywołanie zwyczajnie zwraca liczbę kiedy wykonujemy MoveNext – ani w środku, ani sama z siebie nie powoduje żadnych nieskończonych pętli. Jednakże ciągle trzeba być ostrożnym używając tego kodu. Podanie go jako argument do foreach spowoduje nieskończoną pętlę, ponieważ foreach będzie kontynuować wzywanie MoveNext dopóki ta metoda nie zwróci fałszu, co nigdy się nie stanie w przypadku sekwencji generowanej przez metodę GetNumbers!

 

var sq = GetNumbers().Where(n => n % 2 == 0).Select(n => n * n);


                Teraz spójrzmy na to, co się stanie gdy użyjemy zapytania LINQ operującego na nieskończonej sekwencji, którą właśnie zdeklarowaliśmy. W poniższym przykładzie używamy metody Where rozszerzenia, żeby odfiltrować tylko równe liczby i metody Select rozszerzenia żeby obliczyć kwadrat odfiltrowanej (równej) liczby:

 

var sq = from n in GetNumbers() where n % 2 == 0 select n * n;


Możemy użyć zrozumiałego zapytania z C# 3.0, żeby napisać semantycznie taki sam kod:

                Czy to spowoduje nieskończoną pętlę? Nie, ponieważ ciągle pracujemy z opóźnionymi wykonaniami sekwencji reprezentowanych przez IEnumerable<int>. Wywołanie operatora Where zapytania zwraca nową sekwencje z metodą MoveNext, z tym, że ta, wywoływana, iteruje po danej sekwencji dopóki nie znajdzie równej liczby. Podobnie, pojedynczy krok w sekwencji zwracany przez operator Select polega tylko na przeliczeniu kwadratu wziętego elementu. Jedynym pozostającym problem jest to, że musimy być ostrożni podczas wyświetlania sekwencji, ponieważ nie możemy po prostu użyć foreach. Na szczęście LINQ dostarcza operator zapytania Take, który zwraca sekwencję zawierająca pierwszych X elementów, więc można napisać taki kod:

 

foreach(int n in sq.Take(10))
  Console.WriteLine(n);

            

                Widać wyraźnie, że Where i Select to nie wszystkie operatory zapytania, których można używać z nieskończonymi sekwencjami, ale trzeba być ostrożnym: na przykład Aggregate, Reverse albo inne operatory łączące muszą iterować po wszystkich elementach, co nie jest możliwe pracując z sekwencjami nieskończonymi. Ostatecznie, można implementować własne iteratory do wykonywania operacji, które nie są dostępne w standardowych operacjach zapytań LINQ – po więcej informacji można zajrzeć do artykułu „Własne interatory” Billa Wagnera w Centrum Programistów C#.

[Koniec tłumaczenia części pierwszej :). Są chętni na drugą?]

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: , , , | Categories: .Net, Cloud Computing Posted by karol.ch on 4/1/2009 11:44 AM | Comments (0)

Podczas MIX2009 zaprezentowano rozwiązanie, które powoduje, że nie mogę oprzeć się pytaniu:

Czyżby MS zaczął poważnie traktować PHP, o którym do niedawna w środowisku mówiło się, że "niedługo umrze"?

Nie wiem :P. W każdym razie bardzo zaciekawił mnie post: http://blogs.msdn.com/windowsazure/archive/2009/03/18/using-3rd-party-programming-languages-via-fastcgi.aspx

Autorzy podają, że na Windows Azure można postawić dowolne "serwery" "firm trzecich" takie jak PHP.

Najpierw odpowiednia konfiguracja, a potem tylko taki kod w Web.config:

<configuration>

  <system.webServer>

    <handlers>

      <add name="PHP via FastCGI"

           path="*.php"

           verb="*"

           modules="FastCgiModule"

           scriptProcessor="%RoleRoot%\php\php-cgi.exe"

           resourceType="Unspecified" />

    </handlers>
  </system.webServer>

</configuration>

 

I powinno śmigać :). Ktoś próbował? Ja niestety nie ma na razie możliwości przetestować tego rozwiązania. Chociaż brzmi bardzo obiecująco :).


Źródło:
http://blogs.msdn.com/windowsazure/archive/2009/03/18/using-3rd-party-programming-languages-via-fastcgi.aspx

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: , , , , , | Categories: .Net Posted by karol.ch on 3/29/2009 12:27 AM | Comments (1)

Pod adresem http://www.manoli.net/csharpformat/ znajduje się narzędzie, dzięki któremu można "pokolorować" swój kod C#. Wrzucamy kod C# (czysty tekst), a dostajemy kolorowy HTML.

Auto narzędzia podje, że można nim formatować i kolorować także kody języków VB, HTML, XML, T-SQL or MSH (code name Monad).

Przykład pokazuje efekt działania tego narzędzia. Ja używam go jako rozszerzenia do BlogEngine.Net (efekt). Trzeba niestety przyznać, że w BE ma kilka niedoróbek, jak chociażby numerowanie linii powodujące "dziwne rozjeżdżanie się" pozostałej części strony.

Currently rated 1.0 by 1 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: , , , , , , , , | Categories: .Net Posted by karol.ch on 3/26/2009 10:37 PM | Comments (3)

W zasadzie, to publikuje ten kod, żeby zebrać feedback i dowiedzieć się w jakim kierunku ewentualnie rozwijać poniższą klasę.

Jest to bardzo, bardzo prosta klasa służąca do umieszczenia wpisu na blogu opartym o mechanizmy XMLRPC – np. WordPress, BlogEngine.Net. Ten konkretny przykład testowałem dla WordPressa i działa bez zarzutu. Jest kilka zmiennych nadmiarowych – posłużą do dalszego rozwoju :).

Wsparcie, jak zawsze mile widziane :).

[code:c#]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;
using System.Web;

namespace WordPress_Updater
{
    class blogUpdater
    {
        int postID;
        private string login;
        private string pass;
        private string url;
        public string title;
        public string content;
        private string postXML;
        private string action;
        private string dataToPost;
        public string serverResponse;
        public string categories;
        private string xmlParams;

        public blogUpdater(string _url, string _login, string _password)
        {
            this.login = _login;
            this.pass = _password;
            this.url = _url;
        }


        private string post2xml(string _title, string _categories, string _content)
        {
            string postXML = "<title>" + _title + "</title>" +
                "<category>" + _categories + "</category>" +
                _content;

            return postXML;
        }


        private void addXmlParam(string _type, string _value)
        {
            xmlParams += "<param>" +
                            " <value>";
            if (_value != "") xmlParams += "  <" + _type + ">" + _value + "</" + _type + ">";
            else xmlParams += "<" + _type + "/>";

            xmlParams += " </value>" +
                          " </param>";
        }


        public bool newPost()
        {
            this.action = "blogger.newPost";
            xmlParams = string.Empty;
            postXML = post2xml(this.title, this.categories, this.content);
            postXML = HttpUtility.HtmlEncode(postXML);

            this.dataToPost = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>" +
                "<methodCall>" +
                "<methodName>" + action + "</methodName>" +
                "<params>";
            this.addXmlParam("string", "");
            this.addXmlParam("string", "");
            this.addXmlParam("string", this.login);
            this.addXmlParam("string", this.pass);
            this.addXmlParam("string", postXML);
            this.addXmlParam("boolean", "1");
            this.dataToPost += this.xmlParams;
            this.dataToPost += "</params>" +
                "</methodCall>";
           
            return sendRequest();
        }


        private bool sendRequest()
        {
            WebRequest web = WebRequest.Create(this.url);
            web.Method = "POST";
            //web.ContentLength = this.dataToPost.Length;
            web.ContentType = "text/xml";

            Stream request = web.GetRequestStream();
            StreamWriter sw = new StreamWriter(request);
            sw.Write(this.dataToPost);
            sw.Flush();
            sw.Close();
            request.Close();

            WebResponse response = web.GetResponse();
            Stream responseData = response.GetResponseStream();
            StreamReader sr = new StreamReader(responseData);
            this.serverResponse = sr.ReadToEnd();

            sr.Close();
            responseData.Close();
            response.Close();

            return true;
        }


    }
}
[/code]

Jak używać tego kodu?

[code:c#]
            blogUpdater wp = new blogUpdater("http://PrzykladowyBlog***.wordpress.com/xmlrpc.php", login, haslo);
                    wp.content = “Treść wpisu”;
                    wp.title = “Tytuł wpisu”;
                    wp.categories = "0"; //do jakich kategorii chcemy go dodać – podajemy id po przecinku
                    wp.newPost();
                    //wp.serverResponse //odpowiedź XML serwera
[/code]

Currently rated 4.3 by 3 people

  • Currently 4.333333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: , , , , | Categories: .Net Posted by karol.ch on 3/13/2009 12:22 PM | Comments (1)

Tytuł nieco przewrotny, ale już tłumaczę o co chodzi.

Pomysł napisania tej notki podsunęło mi oczywiście poranne przeglądanie blogów. Nie wszyscy wiedzą, że na platformie .Net  liczby parsowane są zależnie od kultury językowej systemu operacyjnego. Co to oznacza? Dokładne info poniżej:

http://www.moserware.com/2008/02/does-your-code-pass-turkey-test.html

Zapraszam do przeczytania. Warto :)

 

To jest wpis zaimportowany ze starego bloga

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: , , , , , , , , , , , , | Categories: Webmaster, .Net Posted by karol.ch on 3/13/2009 12:18 PM | Comments (0)

Pracuję nad kontrolką dynamicznej mapy (takiej jak Google Maps, czy Live Maps). Chciałbym otworzyć kody źródłowe i umieścić je tutaj :). Mam nadzieję, że będzie to możliwe. Na razie próbka możliwości:

Kontrolka dostarczana jest w postaci pliku *.dll. Jeśli chcemy, można zaimplementować własny provider cache:

            MapControl1.StoredData.Provider = Cache; //OR null


Kontrolka implementuje cały interfejs programistyczny dostarczany przez Google Maps dodając potężny Cache. Dlaczego to takie ważne? Wyobraźmy sobie, że za każdym wyświetleniem mapy chcemy stawiać na niej kilka punktów po stronie użytkownika (JavaScript) - to jest ok. Ale jeśli chcemy postawić ich kilkadziesiąt, albo kilkaset... Będzie to trwało dość długo - żeby nie powiedzieć, że odstraszy użytkowników od wyświetlania naszej mapki. Dzięki cache kontrolki ten problem przestaje istnieć.

Ale służy ona nie tylko do wyświetlania dynamicznych i statycznych map. Jest też dobrym narzędziem do manipulowania i przechowywania kodu KML.

Starałem się zrobić ją tak żeby zmiana wymagań owocowała jak najmniejszymi zmianami w kodzie. I tak żeby zdecydować czy chcemy pokazywać mapę dynamiczną, czy statyczną wystarczy zmienić wartość jednej zmiennej - resztę kodu pozostawiamy tak jak była (wszystkie dodane placemarki, obrazki i nałożone trasy). To kontrolka ma się zatroszczyć o konwersję tych danych na odpowiednią postać - także postać KML.

Mam nadzieję, że opis jest jasny i przyjazny. Jak zawsze - sugestie mile widziane :)

Technologie:
C# 2.0
MSSQL
ASP.NET 2.0

 

To jest wpis zaimportowany ze starego bloga.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags: , , , , , , , , , , | Categories: Wdrożenia, .Net, Aplikacje biznesowe Posted by karol.ch on 3/13/2009 12:16 PM | Comments (0)

Docelowo aplikacja ma posiadać nie tylko opcje przechowywania wszelakich danych o aucie - np. wszystkich z dowodu. Będzie przechowywać także jego historię (logować nowe wydarzenia takie jak malowanie, wypadek itd.). Chociaż jej głównym celem jest pełnienie roli "ToDo" dla osoby zajmującej się flotą firmy. Program będzie przypominał np. o tym, że kończy się przegląd, trzeba wymienić dowód czy olej....

Takie są założenia. Większość z nich jest już zrealizowana. Jeśli będzie taka możliwość zamieszczę odpowiednie zrzuty ekranu.

Technologia:
C# 3.5 (zgodność 2.0)
MSSQL
Windows Form

To jest wpis zaimportowany ze starego bloga

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5