wtorek, 30 grudnia 2014

[Linux] VirtualBox, CentOS - konfiguracja sieci

Stawiając maszynę wirtualną z linuksem potrzebujemy skonfigurować sieć. Po stronie VirtualBoxa zmieniamy ustawienia w zakładce Network:


Następnie należy zalogować się na konto roota na maszynie wirtualnej z CentOS-em i wykonać następujące polecenia:

  • Wyedytować plik z konfiguracją interfejsu sieciowego (najlepiej ustawić na statyczny adres IP)

vi  /etc/sysconfig/network-scripts/ifcfg-eth0

Jako zawartość ustawiamy to co poniżej (nie zmieniając HADDR)

    DEVICE=eth0

    BOOTPROTO=static

    ONBOOT=yes

    NM_CONTROLLED=no

    HWADDR=08:00:27:08:47:E9

    IPADDR=192.168.1.30

    NETMASK=255.255.255.0

    GATEWAY=192.168.1.1

  • Restartujemy interfejsy sieciowe

service network restart

  • Ustawiamy adresy dns

vi /etc/resolv.conf


nameserver 8.8.8.8
nameserver 8.8.4.4

środa, 17 grudnia 2014

[C#|Visual Studio] ASP .NET SignalR: .NET Hubs Client API

Pracę z klientem .NET zaczynamy od zainstalowania odpowiedniego pakietu NuGet-a.

Komunikacja z Hubami odbywa się w sposób asynchroniczny zarówno ze strony JavaScript, jak i .NET. Mamy zatem do czynienia z programowaniem opartym o Taski, z których w C# 5.0 możemy w wygodny sposób korzystać przy użyciu słów kluczowych async/await.

API przypomina nieco to dostępne po stronie JS, nie wykorzystujące dynamicznego proxy. Kluczową klasą jest HubConnection tworzące proxy do konkretnego Huba. Interfejs IHubProxy udostępnia dwie ważne metody: Invoke (do wysyłania danych do serwera) oraz On (do obsługi wiadomości przychodzących).

static async Task Execute()
{
    const string url = "http://localhost:1968";
    var connection = new HubConnection(url);
    var echo = connection.CreateHubProxy("modernChat");

    await connection.Start();
    Console.WriteLine("Connected, transport is: {0}", connection.Transport.Name);
    
    echo.On<string>("newMessageFrom", message => Console.Write(message));

    var response = await echo.Invoke<string>("SendMessage", "hello!");
    
    Console.ReadLine();
}

[C#|Visual Studio] ASP .NET SignalR: JavaScript Hubs Client API

Najczęściej komunikować z hubami będziemy się chcieli z poziomu kodu wykonywanego w środowisku przeglądarki. Klient oparty na bibliotece jQuery nie jest jednak jedynym dostępnym klientem signalR. Do dyspozycji mamy także klienta .NET oraz między innymi WP8, WinRT czy C++. Konsumentami mogą być także inne huby.

Klient JS może komunikować się z serwerem w dwóch trybach:

  • bazującym na późnym wiązaniu i opartym na wołaniu metod i zdarzeń poprzez podawanie ich nazw jako stringów
  • bardziej zaawansowanym, opartym na dynamicznie wygenerowanych proxy 
Kluczem do dynamicznego proxy jest endpoint /signalr/hubs/, który generuje kod kliencki na podstawie kodu w .NET. Kod taki można także wygenerować statycznie za pomocą narzędzie signalr.exe (NuGet Microsoft.AspNet.SignalR.Utils).

Przykładowe wywołania klienckie w oparciu o dynamic proxy.
<script>
    $(function () {
        var hub = $.connection.modernChat;

        hub.client.newMessage = function(msg){
         console.log(msg);
        }

        $.connection.hub
            .start()
            .done(function () {
          hub.server.sendMessage('Hello');    
            });
    });
</script>

Huby stają się propercjami na $.connection. Wszystkie metody pogrupowane są w hub.server.* (metody zdefiniowane po stronie serwera) oraz hub.client.* (metody klienckie wołane przez serwer). Wywołanie metody start rozpoczyna asynchroniczne negocjowanie protokołu i zwraca obiekt promise. Jako parametr można przekazać obiekt, w którym wybierzemy, z jakich sposobów transportu chcemy korzystać (SignalR wybierze ten najlepszy).

var started = hub.start({
    transport: [
        'webSockets',
        'longPolling',
        'serverSentEvents',
        'foreverFrame'
    ]
});

started.done(function () {
    console.log('connected, transport: ' +
       hub.transport.name);
});

Do celów diagnostycznych warto uruchomić po stronie klienckiej tryb konsolowego logowania za pomocą poniższego polecenia.

$.connection.hub.logging = true;

Przy użyciu late binding możemy uzyskać identyczny jak powyżej efekt w poniższy sposób.


var connection = $.hubConnection();
var proxy = connection.createHubProxy('modernChat');
proxy.on('newMessage', function(msg){
 console.log(msg);
});
connection.start();
proxy.invoke('sendMessage', 'Hello');

poniedziałek, 15 grudnia 2014

[C#|Visual Studio] ASP .NET SignalR: Hubs

Kod serwerowy można pisać na dwóch poziomach abstrakcji. Niskopoziomowo możemy wykorzystać tzw. Persistent Connection, natomiast prostszym modelem, wystarczającym do większości potrzeb są Huby. Hub można postrzegać jako zbiór metod wystawionych przez serwer do dwukierunkowej komunikacji z klientem. Nazwy metod powinny odpowiadać biznesowym operacjom, dlatego zasadna wydaje się analogia do kontrolerów ze wzorca MVC. Nie powinniśmy nigdzie w kodzie przechowywać referencji do naszych hubów - nie mamy kontroli nad ich cyklem życia, a zatem nie warto także przechowywać stanu bezpośrednio w hubie. Każda publiczna metoda może być wołana z zewnątrz (zostanie dodana do dynamicznie generowanego klienckiego proxy). Serwer może też wołać dowolną metodę kliencką dzięki Dynamic Language Runtime. Wywołanie takie sprowadzi się do serializacji metody i jej parametrów. Domyślnym serializatorem jest JSON.NET.

[HubName("modernChat")]
public class ModernChatHub : Hub
{
    public void SendMessage(string message)
    {
        Clients.All.newMessageFrom(Context.ConnectionId);
        Clients.Caller.acknowledged();
        Clients.Others.postMessage(message);
    }

    public void Subscribe(string groupName)
    {
        Groups.Add(Context.ConnectionId, groupName);
    }

    public void Unsubscribe(string groupName)
    {
        Groups.Remove(Context.ConnectionId, groupName);
    }

    public void Hello(string groupName)
    {
        var msg = string.Format("Welcome from {0}",
            groupName);
        Clients.Group(groupName).greetings(msg);
    }

    public override Task OnConnected()
    {
        var dependencyResolver = GlobalHost.DependencyResolver;
        var connectionManager = dependencyResolver.Resolve<IConnectionManager>();
        var hubContext = connectionManager.GetHubContext<ModernChatHub>();
        var all = hubContext.Clients.All;
        all.connected(Context.ConnectionId);
        return base.OnConnected();
    }
}

Mamy do dyspozycji kilka możliwości przetwarzania wiadomości. Możemy skorzystać z property Clients, wysyłając wiadomości do nadawcy, do wszystkich, do wszystkich poza nadawcą. Można także selektywnie wybierać odbiorców po id połączenia. Property Context zawiera także cookies, tożsamość użytkownika czy query string.

Kolejnym modelem są grupy agregujące użytkowników wg pewnego klucza. Trzeba pamiętać, że SignalR w żaden sposób nie przechowuje stanu po stronie serwera, co otwiera znakomite możliwości skalowalności, ale też nie zapamięta nam tego, kto był w której grupie przy restarcie aplikacji. Grupa jest zatem jedynie zrzeszeniem kilku połączeń. Grupy są tworzone w sposób dynamiczny (jeżeli łączymy się do grupy, która nie istnieje, to zostanie założona). Jedno połączenie może być skojarzone z wieloma grupami.

Ostatni przykład, to zdarzenia, do których mamy dostęp z poziomu Hub-a, takie jak OnConnected, OnDisconnected oraz OnReconnected. Wewnątrz nich możemy wołać dowolny kod. Jeżeli chcemy notyfikować podłączonych klientów spoza Huba, możemy skorzystać z DependencyResolvera (odpowiednik ServiceLocatora).

[C#|Visual Studio] ASP .NET SignalR: Wprowadzenie

ASP .NET SignalR to genialny framework rozwiązujący problem notyfikacji serwerowych i komunikacji typu push. Wraz z rozwojem sieci i technologii z nią związanych, pojawia się potrzeba tworzenia serwisów dostarczających dane użytkownikom "w czasie rzeczywistym" i takich, które będą w stanie same dostarczać dane na dowolne urządzenie (przeglądarka, desktop, aplikacje mobilne). Całą sieć do tej pory opierała się głównie na protokole HTTP, który jest mechanizmem typu pull (klient wysyła request i otrzymuje odpowiedź od serwera). Serwis typu push działa tak, że otwiera połączenia od klientów i notyfikuje ich o zmianach w jakimś źródle danych (np. w tabeli bazy danych). Podobnie działają mechanizmy typu publish - subscribe (np. MSMQ), ale potrzebujemy czegoś, co będzie dobrze działało na każdej platformie i każdym urządzeniu.

Programowanie w SignalR daje właśnie taki model ideowy zapewniając dobór technologii odpowiadającej możliwościom urządzenia klienckiego. Serwisy typu push są w SignalR zaimplementowane na cztery sposoby, rozpoczynając od tych najmniej wydajnych, a kończąc na najwydajniejszych:

  1. Long polling - mechanizm cyklicznego odpytywania serwera AJAX-owymi zapytaniami. Zapytanie takie ma ustawiony długi timeout (np. 30 sekund), a serwer nie odpowiada na nie od razu, ale w momencie, gdy pojawią mu się jakieś dane do wysłania. Jeżeli serwer nie ma nic ciekawego do wysłania, to nie wysyła odpowiedzi, a klient ponowi żądanie za 30 sekund
  2. Forever frame - po stronie klienta pojawia się ukryty iFrame, który wysyła zapytanie do serwera. Serwer zwraca odpowiedzi z nagłówkiem Transfer-encoding: chunked, który pozwala na wysłanie odpowiedzi w kilku paczkach. Każda taka wiadomość jest wysyłana tylko wtedy, kiedy na serwerze pojawią się nowe dane. Serwer wysyła wiadomości, które wstrzykują skrypt wywołujący jakąś metodę po stronie klienta.
  3.       
  4. Server-sent events - jednokierunkowy model komunikacji, w którym serwer wysyła do klienta zdarzenia. Wykorzystuje ideę persistent connection (reużywania połączenia TCP do wysłania wielu requestów / responsów w oparciu o nagłówek connection: 'keep-alive'). Wiadomości takie wykorzystują specjalny content-type: text/event-stream, a po stronie klienta także obiekt EventSource
  5. WebSocket - komunikacja dwukierunkowa, oparta na prostym API WebSocket ze specyfikacji HTML5. Przeglądarka negocjuje z serwerem upgrade protokołu z HTTP/HTTPS na odpowiednio WS lub WSS i jeżeli serwer wyrazi zgodę (kod HTTP 101), to połaczenie TCP/IP zostanie użyte do otwarcia dwukierunkowego kanału pomiędzy klientem, a serwerem. Po stronie JS mamy do dyspozycji obiekt WebSocket.
SignalR może być osadzony w aplikacji ASP.NET lub jako self-host. Pracę z tym frameworkiem najlepiej rozpocząć od dodania kilku NuGetów:



Następnie tworzymy najprostszy rodzaj huba - echo, które będzie odpowiadało na klienckie wiadomości.

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (WebApp.Start<WsStartup>("http://localhost:1968"))
            {
                Console.WriteLine("Server running!");
                Console.ReadLine();
            }
        }
    }

    public class WsStartup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            app.MapSignalR();
        }
    }

    [HubName("echo")]
    public class EchoHub : Hub
    {
        public string Call(string text)
        {
            return text + " from hub";
        }
    }
}

Wywołanie metody WebApp.Start("http://localhost:1968") powoduje zainicjalizowanie endpointów SignalR za pomocą klasy Startup pod wyspecyfikowanym adresem. Atrybut HubName określna przyjazną nazwę, po której będzie łączył się do niego klient. 

Najprostszy przykład kodu klienckiego (wysyłający wiadomość i wyświetlający odpowiedź) wygląda następująco:
 

<!DOCTYPE html>
<html >
<head>
    <title></title>
    <script src="Scripts/jquery-2.1.0.js"></script>
    <script src="Scripts/jquery.signalR-2.0.2.js"></script>
    <script src="/signalr/hubs"></script>
    <script>
        $(function () {
            var hub = $.connection.echo;
            $.connection.hub
                .start()
                .done(function () {
                    hub.server.call('Hello SignalR!').done(function(msg){
                      alert(msg);
                    });;
                });
        });
    </script>
</head>
<body>
</body>
</html>

Trzeci tag <script> wskazuje na dynamiczny endpoint /signalr/hubs wystawiony przez serwer. Endpoint ten generuje w locie kod JS na podstawie dostępnych hubów. Dzięki niemu możemy pobrać referencję do naszego huba ($.connection.echo). Następnie w asynchroniczny sposób zostaje wołana metoda start. Metoda ta zwraca obiekt promise, w którym możemy zasubskrybować się na metodzie done, gdzie możemy wołać kod z naszego huba.

niedziela, 26 października 2014

[HTML|JS|CSS] CSS3: Flexbox

Layout w HTML + CSS zawsze był problemem. W ostatnim czasie coraz więcej przeglądarek wspiera nowe rozwiązanie dotyczące layoutów - flexboxy. Problem jest prosty: mamy kontener i chcemy w nim rozmieścić elementy.


<div id="flexbox1">
 <div>1</div>
    <div>2</div>
    <div>3</div>
</div>

Korzystając z propercji display ustawionej na flex oraz ustawiając na kontenerze flex-direction na jedną z możliwych opcji, możemy uzyskać następujące efekty:




.flexbox {
    display: flex;
    flex-direction:row;
    border: 1px solid black;
    margin-top: 10px;
    min-height: 15px;
    width: 200px;    
}

Domyślnie kontener ustawi nam się na 100% szerokości. Modyfikować możemy też style w elementach kontenera. Mamy do dyspozycji propercje order oraz flex-grow.


Jeśli chodzi o sam kontener, to pozostałymi ciekawymi opcjami są flex-wrap oraz justify-content.

sobota, 16 sierpnia 2014

[C#|Visual Studio] Rhino Mocks

Idealny Unit Test to taki, który jest:
  1. atomowy (testujemy tylko jeden fragment funkcjonalności)
  2. deterministyczny
  3. powtarzalny
  4. niezależny od kolejności wywoływania innych testów 
  5. szybki (czas wykonania rzędu milisekund)
  6. łatwy do uruchomienia
 Problemem zawsze będą zależności. Przeważnie metoda poddawana testowi woła metody innych klas, które mogą wykonywać wolne operacje, np. łączenie się z bazą danych. Co więcej testowanie metod w ten sposób narusza zasadę atomowości Unit Testów.

W tym przypadku z pomocą przychodzi zasada Dependency Inversion. Zamiast wstrzykiwać do testowanego serwisu właściwe zależności, możemy na etapie UT wstrzyknąć inną implementację danego interfejsu wykonującą tylko tyle kodu, ile potrzebujemy. Problem polega na tym, że wraz ze wzrostem komplikacji właściwych serwisów musimy także utrzymywać kod mockowanych serwisów.

Tu z pomocą przychodzi Rhino Mocks - framework budujący dynamiczne mocki (wykorzystując obiekty proxy) na potrzeby naszych testów.

 Mockowanie rozpoczynamy od użycia klasy MockRepository, która stworzy nam mock dla dowolnego interfejsu. Mock taki będzie zawierał puste metody (dla metod zwracających void) lub metody zwracające wartość domyślną dla pozostałych metod z interfejsu.

Przykładowo mamy klasę InvoiceService, która woła jedną ze swoich zależności - InvoiceRepository.

public class Invoice
{
    public string Id { get; set; }
    public decimal Amount { get; set; }
    public string UserId { get; set; }
}

public interface IInvoiceRepository
{
    bool Store(Invoice entity);
}

public class InvoiceRepository : IInvoiceRepository
{
    public bool Store(Invoice entity)
    {
        //Long running SQL operation
        return true;
    }
}

public class InvoiceService
{
    private IInvoiceRepository _invoiceRepository;

    public InvoiceService(IInvoiceRepository invoiceRepository)
    {
        _invoiceRepository = invoiceRepository;
    }

    public void SaveInvoice(Invoice item)
    {
        var success = _invoiceRepository.Store(item);
        if(!success)
            throw new Exception("Unable to save");
    }
}

Chcemy zamockować interfejs IInvoiceRepository w ten sposób, by zwracał true, jeżeli podamy fakturę różną od null.

[Test]
public static void InvoiceService_ShouldCallInvoiceRepository()
{
    //Arrange
    IInvoiceRepository repositoryMock = MockRepository.GenerateMock<IInvoiceRepository>();
    repositoryMock.Stub(x => x.Store(Arg<Invoice>.Is.NotNull)).Return(true);

    Debug.WriteLine(repositoryMock.GetType().FullName);
    var service = new InvoiceService(repositoryMock);

    //Act
    service.SaveInvoice(new Invoice());

    //Assert
    repositoryMock.AssertWasCalled(s => s.Store(Arg<Invoice>.Is.Anything));
}

Na konsoli wypisze się: Castle.Proxies.IInvoiceRepositoryProxyc9859a0ce17d461faef8b8deb39a407c, ponieważ RhinoMocks korzysta z mechanizmu Castle.DynamicProxy.

Zamiast parametru Anything moglibyśmy podać referencję do obiektu faktury przekazywanej do metody SaveInvoice. Często zdarza się też tak, że metoda przyjmuje kilka parametrów, na podstawie których budowany jest obiekt. Tu z pomocą przychodzi mechanizm constraintów.

Rozszerzamy nasz serwis o dodatkową metodę:

public class InvoiceService
{
    //...
    public void SaveInvoice(string id, string userId, decimal amount)
    {
        SaveInvoice(new Invoice()
                        {
                            Amount = amount,
                            Id = id,
                            UserId = userId
                        });
    }
}

I za pomocą metody Matches podajemy warunki, jakie muszą być spełnione.


[Test]
public static void InvoiceService_ShouldCallInvoiceRepository_AndSaveInvoiceWithSameProperties()
{
    //Arrange
    IInvoiceRepository repositoryMock = MockRepository.GenerateMock<IInvoiceRepository>();
    repositoryMock.Stub(x => x.Store(Arg<Invoice>.Is.NotNull)).Return(true);
    string id = "12";
    string userId = "5";
    decimal amount = 100;

    var service = new InvoiceService(repositoryMock);

    //Act
    service.SaveInvoice(id, userId, amount);

    //Assert
    repositoryMock.AssertWasCalled(s => s.Store(Arg<Invoice>.Matches(d => d.Amount == amount 
        && d.UserId == userId)));
}

niedziela, 29 czerwca 2014

[C#|Visual Studio] AOP: Method Interception

Opakowanie metody możemy wykonać zarówno w Castle.DynamicProxy jak i przez Postsharp. Oba podejścia nieco różnią się od siebie.

W przypadku Castle zakładamy, że będziemy korzystać z kontenera IoC. Mamy prosty interfejs IMyInterface oraz prosty typ MyType. Rozpoczynamy od stworzenia interceptora, który będzie logował zdarzenia. Musi on dziedziczyć po interfejsie IInterceptor z przestrzeni nazw IInterceptor. Interfejs ten wystawia metodę Intercept.

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("On Enter");
        try
        {
            invocation.Proceed();
        }
        catch (Exception)
        {
            Console.WriteLine("On Error");
            throw;
        }
        finally
        {
            Console.WriteLine("On Exit");
        }
    }
}

Pozostaje jeszcze skonfigurować odpowiednio kontener i można korzystać z typu opakowanego w intereceptor.

using (var windsorContainer = new WindsorContainer())
{
    windsorContainer.Register(Component.For<LoggingInterceptor>());
    windsorContainer.Register(Component.For<IMyInterface>()
                                    .ImplementedBy<MyType>()
                                    .Interceptors<LoggingInterceptor>());

    var type = windsorContainer.Resolve<IMyInterface>();

    type.Run();
}

W Postsharpie dziedziczymy po bazowej klasie OnMethodBoundaryAspect, która definiuje potrzebne nam metody wirtualne. Ważne, by nasz aspekt oznaczyć atrybutem Serializable.

[Serializable]
public class LoggingInterceptor2: OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.WriteLine("On Entry");
        base.OnEntry(args);
    }

    public override void OnException(MethodExecutionArgs args)
    {
        Console.WriteLine("On Error");
        base.OnException(args);
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Console.WriteLine("On Exit");
        base.OnSuccess(args);
    }
}

Nasza klasa jest atrybutem, który możemy umieścić nad definicją dowolnej metody.

[C#|Visual Studio] AOP: Wprowadzenie

Programowanie aspektowe powstało niejako w odpowiedzi na powtarzające się schematy pisania kodu takie jak na przykład instrukcje try-catch, transakcje, logowanie itd. Aby uniknąć kopiowania kodu wprowadzono komplementarne do OOP pojęcie aspektów. AOP wprowadza kilka ważnych pojęć:
  • cross-cutting concerns - funkcjonalności używane w wielu miejscach w systemie, np. logowanie zdarzeń
  • advice - kod wykonujący cross-cutting concern
  • pointcut - miejsce występowania aspektów (np. wyjście metody abc)
  • tangling - określenie opisujące wymieszanie kodu typu advice z logiką biznesową
  • weaving (dzierganie) - proces wstrzykiwania kodu związanego z aspektem do logiki biznesowej
Cała idea polega na tym, że chcemy oddzielić cross-cutting concerns od właściwej logiki. Często nie wystarczy wydzielenie do nowej klasy, bo mamy np. do czynienia z konstrukcjami języka typu try-catch-finally. AOP daje nam kod czystszy i napisany w bardziej deklaratywny sposób. Programowanie aspektowe zapewnia zachowanie Single Responsibility Principle, a co za tym idzie znacznie ułatwia refaktoryzację. W wielu przypadkach można je porównać do wzorca dekoratora (np. opakowujemy wywołanie metody w dodatkowy kod).

Przykładowe lokalizacje aspektów:
  • przed wywołaniem metody
  • po pomyślnym zakończeniu metody
  • przy rzuceniu wyjątku
  • zawsze po metodzie (wewnątrz bloku finally)

Najpopularniejsze narzędzia związane z  AOP to Postsharp oraz Castle Dynamic Proxy. Postsharp działa na zasadzie postkompilacji modyfikując wytworzone przez Visual Studio assembly. Dodaje on instrukcje IL w wybranych przez nas miejscach. Jest zintegrowany z VS tak, że możemy przeprowadzać dzięki niemu np. walidację postkompilacyjną. Jeżeli assembly nie przejdzie takiej walidacji, to VS zwróci błąd kompilacji.
Instalujemy go NuGetem, przy czym za pełną wersję trzeba zapłacić.



Drugie narzędzie co Castle Dynamic Proxy. Wstrzykiwanie aspektów odbywa się tu runtime-owo i jest powiązane z kontenerami IoC. Odpytując kontener o dany interfejs dostajemy jego implementację opakowaną w kod przerywający wykonanie metody i dodający do niej kod aspektowy. Jest częścią większego frameworka Castle, w którym kontenerem IoC jest Castle Windsor.

sobota, 21 czerwca 2014

[HTML|JS|CSS] HTML: Transformaty XSLT

Transformaty XSLT to popularny mechanizm przetwarzania plików XML. Wynikiem może być HTML, inny XML lub dowolny plik tekstowy. Arkusz XSL zawiera zestaw reguł określających, które fragmenty wejściowego XML-a transformować do wyniku i w jakie dodatkowe informacje je uzupełnić. Ścieżki podajemy za pomocą XPATH-a.

Najprostszy przykład użycia XSLT to hostowanie pliku XML. Nie chcemy wyświetlać go bezpośrednio użytkownikowi, dlatego decydujemy się na prostą transformację do HTML-a. W tym celu w drugiej linii XML-a umieszczamy link do transformaty.

<?xml version="1.0"?>
<?xml-stylesheet href="mytransform.xsl" type="text/xsl"?>

Szablon powinien składać się z tzw. template'ów czyli fragmentów kodu dopasowanych do elementów XML-a, które mają one przetwarzać. Przykładowo template, który zastosuje się do roota XML-a:

<xsl:template match="/">
  <html>
  <body>
  <h2>My books</h2>  
  <xsl:apply-templates/>  
  </body>
  </html>
</xsl:template>

Instrukcja apply-templates spowoduje wykonanie się pozostałych szablonów pasujących do elementów wewnątrz root-a. Wewnątrz tego pliku mamy jeszcze zdefiniowany szablon pasujący do elementów typu catalog.

<xsl:template match="catalog">
  <table>
   <thead>
    <tr>
     <th>Title</th>
     <th>Author</th>
     <th>Price category</th>
    </tr>
   </thead>
    <xsl:for-each select="book">
     <xsl:if test="./attribute::id != $hiddenId">
     <tr>
      <td>
       <xsl:value-of select="title" />
      </td>
      <td>
       <xsl:value-of select="author" />
      </td>
      <td>
       <xsl:choose>
        <xsl:when test="price &gt; 10 and price &lt; 50">
         cheap
        </xsl:when>
        <xsl:when test="price &gt; 50 and price &lt; 100">
         medium
        </xsl:when>
        <xsl:otherwise>expensive</xsl:otherwise>
       </xsl:choose>
      </td>
     </tr>
     </xsl:if>
    </xsl:for-each>
  </table>
</xsl:template>

Szablon taki buduje tabelę przechodząc po wszystkich elementach typu book za pomocą instrukcji for-each. Mamy także do dyspozycji dwie instrukcje sterujące: prostszą xsl-if (sprawdza tylko, czy dany fragment kodu ma się wykonać) oraz bardziej złożoną xsl-choose (z uwzględnieniem wielu warunków, odpowiada switchowi z języka C). Zapis ./ oznacza odwołanie do obecnie przetwarzanego elementu, natomiast poprzez /attribute::nazwa możemy wyciągać wartości z atrybutów. XSLT pozwala także na definiowanie własnych zmiennych, do których odwołujemy się przez $zmienna, np.

<xsl:variable name="hiddenId" select="'bk101'"/>

niedziela, 15 czerwca 2014

[C#|Visual Studio] Threading: Interlocked

Interlocked to klasa wystawiająca statyczne metody, które pozwalają uczynić pewne podstawowe operacje atomowymi. W atomowość możemy obłożyć operacje arytmetyczne:

var task1 = Task.Factory.StartNew(() =>
{
    for (int i = 0; i < 50000; i++)
        Interlocked.Increment(ref _variable);
});

var task2 = Task.Factory.StartNew(() =>
{
    for (int i = 0; i < 100000; i++)
        Interlocked.Decrement(ref _variable);
});

var task3 = Task.Factory.StartNew(() =>
{
    for (int i = 0; i < 25001; i++)
        Interlocked.Add(ref _variable, 2);
});

Task.WaitAll(task1, task2, task3);
Console.WriteLine(_variable); //2

, a także operacje podstawienia lub warunkowego podstawienia (jeżeli zmienna ma wartość x, to podstaw y).

private static void Exchange()
{
    Thread thread1 = new Thread(new ThreadStart(A));
    thread1.Start();
    thread1.Join();

    // Written [2]
    Console.WriteLine(Interlocked.Read(ref _value));
}

private static void A()
{
    // Replace value with 10.
    Interlocked.Exchange(ref _value, 10);

    // CompareExchange: if 10, change to 20.
    long result = Interlocked.CompareExchange(ref _value, 20, 10);

    // Returns original value from CompareExchange [1]
    Console.WriteLine(result);
}

Mając do dyspozycji te metody, możemy budować bardziej skomplikowane równoległe algorytmy.

[C#|Visual Studio] String, ToString()

Typ System.String znany także pod aliasem string towarzyszy nam przez całe nasze .NET-owe życie. W tym poście przedstawione zostaną pewne mniej znane konstrukcje, które mogą przydać się w codziennej pracy z C#.

W C# ciągi znaków są immutable, co oznacza, że nie można ich modyfikować. Każda operacja modyfikująca utworzy na stercie nową instancję. Typ System.String dziedziczy po object i implementuje takie interfejsy, jak IComparable, ICloneable, IConvertible, IEnumerable, IEquatable. Dodatkowo w C# można deklarować tzw. verbatim strings - ciągi znaków wewnątrz których każdy znak ma być traktowany jako część ciągu znaków - przed takim stringiem umieszczamy @.

String interning

Jest to technika optymalizująca zużycie pamięci w .NET. Polega ona na tym, że dla każdego ciągu znaków liczony jest hash i taki ciąg znaków wkładany jest do specjalnego słownika, gdzie kluczem jest właśnie ten hash. Słownik istnieje w obrębie całej AppDomain i podczas alokacji nowego string-a, jeżeli wyliczony hash znajduje się w słowniku, to instancja jest reużywana.

Konstruktory

Warto znać przeciążenia konstruktora. Poniżej przykład na to,  jak utworzyć ciąg 10 zer na 4 sposoby. Sposób wpisania literal-u wydaje się najprostszy, ale możemy to zrobić na inne, bardziej wygodne sposoby za pomocą konstruktorów.

char[] array = new char[10];
for (int i = 0; i < array.Length; i++)
    array[i] = '0';

char[] array2 = new char[12];
for (int i = 0; i < array2.Length; i++)
    array2[i] = '0';

Console.WriteLine(new string(array));
Console.WriteLine(new string(array2, 1, array2.Length -2));
Console.WriteLine(new string('0', 10));
Console.WriteLine("0000000000");

StringBuilder

W C# możemy sklejać stringi za pomocą operatora +. W pewnych sytuacjach (wiele sklejeń) jest on jednak bardzo niewydajny, dlatego zaleca się korzystać z klasy StringBuilder. Obiekt taki zawiera pole, które wskazuje na tablicę struktur typu Char. StringBuilder pozwala na manipulowanie taką tablicą. Jeżeli przekroczymy zaalokowane miejsce, to StringBuilder automatycznie skopiuje znaki i zbuduje nową tablicę. Wywołanie ToString spowoduje stworzenie nowego obiektu String na stercie i zwrócenie referencji do niego. Domyślna pojemność StringBuildera to 16 znaków. Jeżeli operacje wykonywane na nim próbują przekroczyć pojemność, to StringBuilder podwaja zaalokowane miejsce.

var random = new Random();
var sb = new StringBuilder();
var next = random.Next() % 100;
while (next % 2 == 0)
{
    sb.Append(next);
    next = random.Next() % 100;
}
Console.WriteLine(sb.ToString());

Instancyjne metody


var str = "Jambalaya";
//IEnumerable extension methods
Console.WriteLine(new string(str.Distinct().ToArray()));

//Walidacja
if(str.EndsWith("ya") && str.StartsWith("Ja") && str.Contains("ala"))
    Console.WriteLine("Matches");

Console.WriteLine(new string(str.Except("aya").ToArray())); //Jmbl
//traktuje aya jako IEnumerable<char>

//Analiza
Console.WriteLine(str.IndexOf('a'));
Console.WriteLine(str.IndexOfAny(new char[] {'a', 'J'}));
Console.WriteLine(str.LastIndexOf('a'));
Console.WriteLine(str.LastIndexOfAny(new char[] { 'l', 'y' }));

//Tworzenie nowych instancji
Console.WriteLine(str.Insert(3, "error")); //Jamerrorbalaya

//Uzupełnia podanym znakiem do zadanej długości (20), domyślnie spacja
Console.WriteLine(str.PadLeft(20, '_')); // ___________Jambalaya
Console.WriteLine(str.PadLeft(20)); //           Jambalaya

//3 oznacza maksymalną liczbę itemów
var items = str.Split(new char[] {'a'}, 3, 
    StringSplitOptions.RemoveEmptyEntries); //J,mb,laya
foreach (var item in items)
    Console.WriteLine(item);

str += "\n \t";
Console.WriteLine(str.Length); //12
//usuwa wszystkie biale spacje
str = str.Trim();
Console.WriteLine(str.Length); //9

Statyczne metody


var s1 = "me";
var s2 = "Mark";
Console.WriteLine(string.Compare(s1, s2)); //1

var s3 = string.Format("{0} and {1} went to school", s1, s2);
Console.WriteLine(s3);

Console.WriteLine(string.IsNullOrEmpty("")); //true
//drugi argument to params
Console.WriteLine(string.Join(",", s1, s2));

 

Numeryczne konwersje


float price = 99.99f;
Console.WriteLine("C - currency: " +
    price.ToString("C")); //99.99 zł
Console.WriteLine(price.ToString("C", 
    CultureInfo.CreateSpecificCulture("en-US"))); //$99.99

int num = 70;
Console.WriteLine("D - decimal: " + num.ToString("D4")); //0070

long number = 70000000000000000;
Console.WriteLine("E - exponential: " + 
    number.ToString("E")); // 7,000000E+016

Console.WriteLine("N - number: " +
    number.ToString("N")); // 70 000 000 000 000 000,00

double perc = 0.02;
Console.WriteLine("P - percent: " + perc.ToString("P")); //2,00%

int value = 1024;
Console.WriteLine("X - hexadecimal: " + value.ToString("X4")); //0040

poniedziałek, 28 kwietnia 2014

[C#|Visual Studio] C#: Reflection

Reflection to potężne narzędzie, za pomocą którego można zrobić wiele dobrego jak również i wiele złego w każdej .NET-owej aplikacji. Najważniejsze klasy, to Type, Assembly, Activator oraz wszystkie opisujące składowe typów, czyli MethodInfo, PropertyInfo, ConstructorInfo, FieldInfo, EventInfo itd. Poza swobodnym przeglądaniem assemblies za pomocą kodu, reflection ma zastosowanie w operacjach wykonywanych dynamicznie na starcie aplikacji. W każdym innym wypadku musimy liczyć się ze sporym spadkiem wydajności w stosunku do kodu statycznie typowanego.

Klasa assembly pozwala na odczytywanie metadanych z różnych assemblies a także ładowanie ich.

var current = Assembly.GetExecutingAssembly();

Console.WriteLine("Current assembly: " + current.FullName);

var fromGac =
    Assembly.Load("System.Xml.Linq,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089");

var restSharpAssembly = Assembly.LoadFrom("RestSharp.dll");

Console.WriteLine("\nLoaded assembly: " + restSharpAssembly.FullName);
var dependant = restSharpAssembly.GetReferencedAssemblies();

Console.WriteLine("\nReferenced assemblies:");
foreach (var assemblyName in dependant)
    Console.WriteLine("\t" + assemblyName.FullName);

Metoda GetExecutingAssembly zwróci nam informacje o assembly, w którym ją wywołujemy (np. plik exe). Za pomocą metody Load możemy ładować assemblies z Global Assembly Cache, podając full name. Z kolei dla assemblies bez strong name możemy użyć metody LoadFrom lub LoadFile szukających na dysku. Jeżeli interesują nas zależne assemblies, możemy uzyskać do nich dostęp przy użyciu metody GetReferencedAssemblies.

Mając obiekt typu Assembly możemy pobrać wszystkie publiczne typy w nim zdefiniowane - służy do tego metoda GetExportedTypes..

Console.WriteLine("\nPublic types:");
            var types = restSharpAssembly.GetExportedTypes();

            foreach (Type type in types)
                Console.WriteLine("\t" + type);

            var stype = (from type in types
                        orderby type.GetCustomAttributes(true).Count() descending
                        select type).First();

            var instance = Activator.CreateInstance(stype);
            Console.WriteLine("\nCreated type instance:" + stype.FullName);

            var props = stype.GetProperties();
            Console.WriteLine("Properties:");
            foreach (var propertyInfo in props)
                Console.WriteLine("\t" + propertyInfo.Name);

            var tfields = (from type in types
                           let fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                           orderby fields.Count() descending
                           select fields).First();

            foreach (var fieldInfo in tfields)
                Console.WriteLine("\t" + fieldInfo.Name);

Na każdym z typów możemy sprawdzić, jakie zdefiniowano atrybuty (GetCustomAttributes), a także pobrać wszystkie properties (GetProperties) czy pola (GetFields), także te prywatne, ustawiając odpowiednie flagi. Klasa Activator pozwala nam na tworzenie instancji dowolnego typu (rzutowanej do object). Mając taką instancję możemy pobrać MethodInfo i wywołać taką metodę przekazując do niej parametry.

var sw = new Stopwatch();
sw.Start();
var jsonArray = new JsonArray();
for (int i = 0; i < 1000000; i++)
{
    jsonArray.Add(i);
}
Console.WriteLine("Invoking instance method: {0} ms", sw.ElapsedMilliseconds);
sw.Restart();

var methodInfo = stype.GetMethod("Add");
for (int i = 0; i < 1000000; i++)
{
    methodInfo.Invoke(instance, new object[] {i});
}
Console.WriteLine("Invoking method via reflection: {0} ms", sw.ElapsedMilliseconds);
sw.Reset();

Porównanie takie wypada zdecydowanie na niekorzyść Reflection, głównie przez iterowanie po metadanych i boxing parametrów wejściowych.

Invoking instance method: 83 ms
Invoking method via reflection: 2241 ms

sobota, 26 kwietnia 2014

[C#|Visual Studio] C#: Cryptography

Podstawowe trzy obszary zastosowań kryptografii, którymi są: wyliczanie haszy, kryptografia symetryczna oraz kryptografia asymetryczna zostały w bardzo dobry sposób zaimplementowane w dot Necie w namespace System.Security.Cryptography. Podstawowe pojęcia związane z kryptografią to: plaintext - wiadomość do zaszyfrowania, szyfrowanie - proces obfuskacji danych, deszyfracja - proces odtwarzania oryginalnych danych oraz ciphertext - dane w postaci zaszyfrowanej. Różne techniki kryprograficzne zapewniają:
  • poufność - dane nie mogą być przeczytane przez nieodpowiednie osoby
  • integralność - możliwość weryfikacji, czy dane były modyfikowane
  • uwierzytelnianie - potwierdzenie tożsamości użytkownika
  • niezaprzeczalność - autor wiadomości nie może się jej wyprzeć

Hashing:

Funkcje haszujące konwertują wejście o zmiennej długości w wyjściowy ciąg bajtów o stałej długości tworząc skrót (nazywany także hashem) z wiadomości. Operacja taka jest nieodwracalna i charakteryzuje się tym, że małe zmiany ciągu wejściowego powodują duże zmiany w ciągu wyjściowym. Haszowanie stosuje się w celu zapewnienia integralności. W .NET mamy dostępne 6 klas dziedziczących po abstrakcyjnej HashAlgorithm. Wybór powinien być kompromisem pomiędzy długością klucza (ataki typu bruteforce), a szybkością wykonywania.

Console.WriteLine("Please enter secret message:");
var msg = Console.ReadLine();
var msgBytes = Encoding.UTF8.GetBytes(msg);

HashAlgorithm[] algorithms = { 
                                 new MD5Cng(),
                                 new MD5CryptoServiceProvider(),
                                 new SHA1Managed(), 
                                 new SHA256Managed(),
                                 new SHA384Managed(),
                                 new SHA512Managed(),
                                 new RIPEMD160Managed()
                             };

var watch = new Stopwatch();
foreach (var hashAlgorithm in algorithms)
{
    watch.Start();
    byte[] hash = null;
    for (int i = 0; i < 100000; i++)
    {
        hash = hashAlgorithm.ComputeHash(msgBytes);
    }
    watch.Stop();
    Console.WriteLine("{0} ({1} bit): {2} ms ", 
        hashAlgorithm.GetType().Name, 8*hash.Length, watch.ElapsedMilliseconds);
    watch.Reset();
    Console.WriteLine(BitConverter.ToString(hash).Replace("-", ""));
}

Uzyskane wyniki:

Please enter secret message:
Hello world!

MD5Cng (128 bit): 933 ms
86FB269D190D2C85F6E0468CECA42A20

MD5CryptoServiceProvider (128 bit): 812 ms
86FB269D190D2C85F6E0468CECA42A20

SHA1Managed (160 bit): 257 ms
D3486AE9136E7856BC42212385EA797094475802

SHA256Managed (256 bit): 375 ms
C0535E4BE2B79FFD93291305436BF889314E4A3FAEC05ECFFCBB7DF31AD9E51A

SHA384Managed (384 bit): 2696 ms
86255FA2C36E4B30969EAE17DC34C772CBEBDFC58B58403900BE87614EB1A34B8780263F255EB5E65CA9BBB8641CCCFE

SHA512Managed (512 bit): 3323 ms
F6CDE2A0F819314CDDE55FC227D8D7DAE3D28CC556222A0A8AD66D91CCAD4AAD6094F517A2182360C9AACF6A3DC323162CB6FD8CDFFEDB0FE038F55E85FFB5B6

RIPEMD160Managed (160 bit): 423 ms
7F772647D88750ADD82D8E1A7A3E5C0902A346A3

Symmetric Algorithms:

Algorytmy symetryczne, to takie, w których do procesu szyfrowania i deszyfrowania używany jest ten sam klucz. Klucz taki musi być przechowywany w odpowiednio bezpiecznych warunkach i mieć odpowiednią długość, żeby uniknąć ataków typu brute-force. Obecnie powszechnie używanym algorytmem jest AES (Rijndael z min.128 bitowymi kluczami). Im dłuższy klucz, tym dłuższe szyfrowanie. Jeżeli chcemy wygenerować sobie klucz, najlepiej skorzystać z klasy RNGCryptoServiceProvider zapewniającej dużo lepszą "losowość", niż pozostałe narzędzia do generacji liczb pseudolosowych. Algorytm Rijndael często używany jest w trybie CBC, gdzie wynik kolejnej rundy szyfrowania zależy od rundy poprzedniej. Stąd obok klucza musimy znać wektor wejściowy (przed pierwszą rundą). Wektor taki - wektor IV (Initialization Vector) podaje się obok klucza przy dystrybucji. Konstruktor klasy RijndaelManaged wygeneruje taki wektor.

private static void Symmetric(byte[] msgBytes)
{
    var key = new byte[256/8];
    RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
    provider.GetBytes(key);

    var cipher = CreateCipher();

    cipher.Key = key;
    var encryptor = cipher.CreateEncryptor();
    var result = encryptor.TransformFinalBlock(msgBytes, 0, msgBytes.Length);

    Console.WriteLine("Secret key: " + BytesToString(key));
    Console.WriteLine("IV: " + BytesToString(cipher.IV));
    Console.WriteLine("Encrypted message: " + BytesToString(result));

    var cipher2 = CreateCipher();
    cipher2.Key = key;
    cipher2.IV = cipher.IV;

    var decryptor = cipher.CreateDecryptor();
    var originalMessage = decryptor.TransformFinalBlock(result, 0, result.Length);

    var s1 = BytesToString(originalMessage);
    var s2 = BytesToString(msgBytes);

    Console.WriteLine("Are messages equal ? " + s1.Equals(s2));
}

private static RijndaelManaged CreateCipher()
{
    RijndaelManaged cipher = new RijndaelManaged();
    cipher.KeySize = 256;
    cipher.BlockSize = 256;
    cipher.Padding = PaddingMode.ISO10126;
    cipher.Mode = CipherMode.CBC;
    return cipher;
}

Asymmetric algorithms:

Kryptografia asymetryczna nazywana także kryptografią klucza publicznego polega na tym, że mamy wygenerowaną parę kluczy: publiczny i prywatny. Klucze te uzupełniają się, to znaczy, że wiadomość zaszyfrowaną kluczem prywatnym można odszyfrować kluczem publicznym i na odwrót. Operacje takie są od 100 do 1000 razy wolniejsze od kryptografii symetrycznej, dlatego często algorytmów asymetrycznych używa się tylko do przesłania symetrycznego klucza sesji. Najpopularniejszy algorytm to RSA. Para kluczy przechowywana jest w kontenerze, przeważnie w systemie operacyjnym, ale można ją też eksportować do pliku XML. Wczytujemy ją z Xml metodę FromString lub podając nazwę kontenera systemowego przy użyciu klasy CspParameters.

CspParameters cp = new CspParameters();
cp.KeyContainerName = "SampleKeys";
cp.Flags = CspProviderFlags.UseMachineKeyStore;
RSACryptoServiceProvider cipher = new RSACryptoServiceProvider(cp);
var bytes = cipher.Encrypt(msgBytes, true);

Console.WriteLine("Encrypted message: " + BytesToString(bytes));
Console.WriteLine(cipher.ToXmlString(includePrivateParameters:true));

var s1 = BytesToString(msgBytes);
var s2 = BytesToString(cipher.Decrypt(bytes, true));

Console.WriteLine("Are messages equal ? " + s1.Equals(s2));

wtorek, 22 kwietnia 2014

[C#|Visual Studio] LINQ: join

Łączenie dwóch kolekcji w LINQ można wykonać na kilka sposobów:
  • inner join
  • group join
  • left outer join
Podstawowy i najczęściej używany sposób to inner join, czyli po prostu zwykłe złączenie kolekcji, przy czym jeżeli istnieją elementy, które nie mają swoich odpowiedników w drugiej kolekcji, to zostaną pominięte.

internal class Team
{
    public int Id { get; set; }
    public string Name { get; set; }
}

internal class Player
{
    public int Id { get; set; }
    public int TeamId { get; set; }
    public string Name { get; set; }
}

//...

var teams = new Team[3];
for (int i = 0; i < teams.Length; i++)
{
    teams[i] = new Team(){Id = i};
}

teams[0].Name = "Liverpool";
teams[1].Name = "Chelsea";
teams[2].Name = "Arsenal";

var players = new Player[3];
for (int i = 1; i <= players.Length; i++)
{
    players[i-1] = new Player() { Id = i - 1, TeamId =  i};

}

players[0].Name = "Hazard";
players[1].Name = "Ramsey";
players[2].Name = "Rooney";

var inner = from player in players
            join team in teams on player.TeamId equals team.Id
            select new
            {
                player.Name,
                TeamName = team.Name
            };

Console.WriteLine("Inner join:");
foreach (var result in inner)
{
    Console.WriteLine("{0}, {1}", result.Name, result.TeamName);
}    

Wypisane zostaną tylko dwa elementy, te, których indeksy TeamId pokrywają się z identyfikatorami drużyn (player[0], player[1])

Group join to konstrukcja sprowadzająca wynik do niepłaskiej struktury przypominającej wynik operacji group by. Operacja ta związana jest ze słowem kluczowym into, a jej wynik jest typu IEnumerable<IEnumerable<T>>. Możemy na tym oczywiście wywołać select spłaszczający wyniki.

var group = from team in teams
            join player in players on team.Id equals player.TeamId
                into playersWithTeams
            select new { Key = team.Name, Count = playersWithTeams.Count() };

foreach (var item in group)
{
    Console.WriteLine("{0}, {1}", item.Key, item.Count);
}

Left outer join przydaje się tam, gdzie z jakichś powodów chcemy dostać wszystkie elementy z kolekcji będącej lewą stroną operacji. Problemem jest, jak przedstawić elementy, które nie mają swojego odpowiednika w kolekcji, będącej prawą stroną join-a. W takim przypadku LINQ dostarcza extension metodę DefaultIfEmpty<T>, gdzie możemy podać, jak ma wyglądać taki "sztuczny" element.

var outer = from player in players
            join team in teams on player.TeamId equals team.Id
                into playersWithTeams
            from item in playersWithTeams.DefaultIfEmpty(new Team() {Name = "<Empty>"})
            select new
                       {
                           item.Name,
                           Player = player.Name
                       };

foreach (var item in outer)
{
    Console.WriteLine("{1}, {0}", item.Name, item.Player);
}            

Zostaną wypisane wszystkie trzy elementy kolekcji players.