wtorek, 20 sierpnia 2013

[C#|Visual Studio] ServiceStack: Wprowadzenie

ServiceStack to framework będący alternatywą dla WCF, WebAPI czy MVC. Jedną z głównych zalet jest cross - platformowość. Autorem Service Stacka nie jest Microsoft, ale community, które udostępnia go na zasadzie open source. Co więcej aplikacje pisane w ServiceStack nie muszą być hostowane na IIS, można je kompilować na Mono i uruchamiań np, na Linuxie.

Nazwa ServiceStack ma symbolizować stos technologii, na jakich budowane są aplikacje.


Kolejnymi względami przemawiającymi za tą technologią są prostota w stosunku do innych frameworków (w ServiceStack mamy do czynienia z konwencjami, które eliminują sporo zbędnych konfiguracji), oraz wydajność poszczególnych komponentów w porównaniu z alternatywnymi technologiami, głównie narzędzia ORM, kontenera IoC, serializator JSON.

W Visual Studio Service Stack instalujemy za pomocą NuGeta.

Przy instalacji do projektu załączane są dodatkowe .dll - ki, takie jak Text (serializacja JSON), Redis (api .NET do bazy NoSql), OrmLite (mapper obiektowo relacyjny).

Web Serwisy pisane w ServiceStacku bazować mają na Data Transfer Objects. Ideę DTO przedstawia poniższy rysunek

Parametrem każdego requestu jest prosty obiekt DTO mający ustawione odpowiednie pola. Jeżeli np. chcemy odpytywać jakąś kolekcję po różnych parametrach, to ustawiamy w danym momencie ten, który nas interesuje w obiekcie DTO.

Strona ServiceStack: http://www.servicestack.net

niedziela, 18 sierpnia 2013

[HTML|JS|CSS] CSS3: calc

Calc to funkcja, która umożliwia przeliczanie różnych jednostek długości w stylach CSS. Wsparcie dla calc dostarcza coraz więcej przeglądarek, niektóre wymagają jeszcze użycia tzw. vendor prefixes.


Przykład użycia calc w Sassie:

@mixin calc($property, $expression) { 
  #{$property}: -moz-calc(#{$expression}); 
  #{$property}: -o-calc(#{$expression}); 
  #{$property}: -webkit-calc(#{$expression}); 
  #{$property}: calc(#{$expression}); 
} 

.outer{
 width: 100%;
 background-color: red;
 height: 100px;
}

.inner{
 @include calc("width","100% - 200px");
 background-color: blue;
 height: 100px;
}

Szerokość wewnętrznego diva będzie przeliczana przy każdej zmianie rozmiaru okna.

.outer {
  width: 100%;
  background-color: red;
  height: 100px; }

.inner {
  width: -moz-calc(100% - 200px);
  width: -o-calc(100% - 200px);
  width: -webkit-calc(100% - 200px);
  width: calc(100% - 200px);
  background-color: blue;
  height: 100px; }

Pozostaje pytanie, co w przypadku, gdy przeglądarka nie obsługuje calc. Do tego, by wykryć, czy przeglądarka wspiera calc wystarczy znana biblioteka Modernizr od wersji 2.6. Samo przeliczenie wystarczy wykonać w JS np. odejmując od szerokości parenta zadaną powyżej szerokość 200px. .

sobota, 17 sierpnia 2013

[HTML|JS|CSS] Wprowadzenie do TypeScript

TypeScript to język stosunkowo nowy (wprowadzony w drugiej połowie 2012 roku), opracowany przez Microsoft i pana Hejlsberga, mocno kojarzonego z językiem C#. TS ma być rozszerzeniem JavaScriptu wprowadzającym pewne znane z języków obiektowych konstrukcje. Pliki o rozszerzeniu .ts kompilowane są przez kompilator TypeScript do czystego JavaScriptu. Produktem, który idzie w parze z nowym językiem, jest Visual Studio 2012, ale sam kompilator jest darmowy i można go pobrać na przykład menadżerem pakietów Node'a, wpisując polecenie:

npm install typescript

Pliki TypeScript kompilujemy z linii poleceń komendą tsc, na przykład polecenie:

tsc sample.ts

utworzy plik o nazwie sample.js lub (oraz) wypisze błędy składniowe na konsoli.
A oto, co więcej poza czystym JavaScriptem daje programistom TypeScript:

  • Klasy i typowalność
Klasy wprowadzają pewną strukturyzację kodu, co jest nieco utrudnione w JS, gdzie obiektami są funkcje. Typowalność z jednej strony zapewnia walidację, z drugiej podpowiadanie składni w VS 2012. Przykład:


//1. classes

class Customer {
    customerId: number;
    companyName: string;
    contactName: string;
    country: string;

    addCustomer(): number {
        return 0;
    }
}

var cust = new Customer();
cust.companyName = "Google";

i wynik kompilacji:

//1. classes
var Customer = (function () {
    function Customer() {
    }
    Customer.prototype.addCustomer = function () {
        //some code here
        return 0;
    };
    return Customer;
})();

var cust = new Customer();
cust.companyName = "Google";

  • Modyfikatory dostępu
Properties w TS mogą być prywatne lub publiczne (domyślnie). Podobnie jak np, w C# do prywatnych nie mamy dostępu spoza klasy. Próba przypisania wartości spowoduje błąd kompilacji. Modyfikatory dostępu wpływają też na to, które properties w VS podpowiada nam IntelliSense.

//2. Access modifiers

class Employee {
    private customerId: number;
    public companyName: string;
    public contactName: string;
    private country: string;

    getEmployeeId(): number{
     return this.customerId;
    }
}

var emp = new Employee();
emp.companyName = "Google";
//error: 'Employee.country is inaccessible'
//emp.country = "USA";


  • Konstruktory, statyczne properties
Wszystko działa dokładnie tak, jak w językach statycznie typowanych.


//3. Constructors, static members

class Person {
    public personId: number;
    public firstName: string;
    public lastName: string;
    static totalPeople: number;

    constructor(){
     Person.totalPeople = Person.totalPeople + 1;
     this.personId = Person.totalPeople;
    }
}

Person.totalPeople = 0;
var p1 = new Person();
var p2 = new Person();
console.log(Person.totalPeople); //2


  • Dziedziczenie
Dziedziczenie, czyli większa reużywalność kodu,


//4. Inheritance

class Driver extends Person{
 public carMake: string;

 constructor(make: string){
  this.carMake = make;
  super();
 }

 getId(): number{
  return this.personId;
 }
}

var dr1 = new Driver("Ford Fiesta");
console.log(dr1.getId());

Ponadto mamy możliwość definiowania interfejsów (słowa kluczowe inteface i implements), odpowiadających interfejsom z C# oraz modułów (słowo kluczowe module) odpowiadających przestrzeniom nazw w C#.

sobota, 10 sierpnia 2013

[C#|Visual Studio] Regex

W tym poście przedstawione zostaną podstawowe przypadki użycia klasy System.Text.RegularExpressions.Regex. Najprostszy sposób użycia, to sprawdzenie, czy tekst zawiera dany ciąg znaków z opcją CaseSensitive lub bez niej.

var bloodBrothers = new string[]
                           {
                               "And if you're taking a walk through the garden of life",
                               "What do you think you'd expect you would see?",
                               "Just like a mirror reflecting the moves of your life",
                               "And in the river reflections of me",

                               "Just for a second a glimpse of my father I see ",
                               "And in a movement he beckons to me",
                               "And in a moment the memories are all that remain",
                               "And all the wounds are reopening again"
                           };

            var pattern = "and";

            foreach (var s in bloodBrothers)
            {
                if(System.Text.RegularExpressions.Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase))
                {
                    Console.WriteLine(s);
                }
            }

Wszystkie stringi rozpoczynające się od danego ciągu znaków:

pattern = "^(And in a).*";

Wszystkie stringi kończące się na danym ciągu znaków:

pattern = "life$";

Wyrazy dłuższe niż 10 znaków:

pattern = "[A-Z|a-z]{10,}";

Numery telefonu, oddzielone znakiem "-" rozpoczynające się od 3 cyfr a kończące na czterech ([0-9] i \d są równoważne)

pattern = "^([0-9]{3})-.*-\\d{4}$";

Trzy takie same cyfry (nawiasy oznaczają grupę,do której następnie odwołujemy się poprzez \1 z krotnością 2, pytajnik oznacza opcjonalność danego znaku)

pattern = "-?(\\d)(\\1){2}-";

Negacja - wszystkie linie nie zaczynające się od A

pattern = "^[^A]";

Skróty znakowe:




Białe spacje i granice wyrazu:

pattern = "\\bdo\\b\\s\\byou\\b";

Case - insensitive z poziomu wzorca:

pattern = "(?i)what";

Linie zakończone pytajnikiem (przy użyciu Unicode)

pattern = "\\u003F$";

Kwantyfikatory:


Lookaheads i lookbehinds:

pattern = "(?=[a-z]{2} life).{2}";

Pattern taki poszuka wszystkich dwuliterowych napisów, po których w dowolnym miejscu w tekście występuje słowo life. Wzorzec ma zerową długość, a więc ostatnia instrukcja {2} oznacza, że wybrane zostaną właśnie te dwuliterowe wyrazy. Pozostałe możliwości to:

  • ?! - negative lookahead
  • ?<=  - lookbehind 
  • ?<! - negative lookbehind

wtorek, 6 sierpnia 2013

[C#|Visual Studio] LINQ to XML

LINQ to XML, jak nazwa wskazuje umożliwia wykonywanie zapytań LINQ na plikach XML wczytywanych do pamięci za pomocą klasy XDocument. Przykładowy plik XML:

<?xml version="1.0" encoding="utf-8" ?>
<peaks>
  <peak>
    <name>Rysy</name>
    <height unit="mnpm">2499</height>
  </peak>
  <peak>
    <name>Swinica</name>
    <height unit="mnpm">2301</height>
  </peak>
  <peak>
    <name>Kasprowy Wierch</name>
    <height unit="mnpm">1987</height>
  </peak>
  <peak>
    <name>Szpiglasowy Wierch</name>
    <height unit="mnpm">2172</height>
  </peak>
</peaks> 

Plik taki możemy odpytywać przy użyciu zapytań LINQ, np.:

//Queries
XDocument xmlDocument = XDocument.Load("tatra.xml");

var twoThousand = from peak in xmlDocument.Root.Elements("peak")
                  let height = int.Parse(peak.Element("height").Value)
                  where height > 2000
                  select peak.Element("name").Value;

foreach (var peak in twoThousand)
    Console.WriteLine(peak);

LINQ to XML to nie tylko odczyt, ale także wygodna możliwość modyfikacji. Aby dodać nowy szczyt wystarczy skorzystać z klasy XElement, dla której jednym z argumentów jest params umożliwiający budowanie drzewa. Przykład poniżej:

//Modifying
var peaks = xmlDocument.Root;
peaks.Add(new XElement("peak", new XElement("name", "Zawrat"),
                       new XElement("height", new XAttribute("unit", "mnpm"), 2159)));

xmlDocument.Save("tatra2.xml");


Również usuwanie elementów jest bardzo proste.

//Deleting
var highest =
    peaks.Elements("peak").OrderByDescending(x => int.Parse(x.Element("height").Value))
    .FirstOrDefault();
highest.Remove();

xmlDocument.Save("tatra3.xml");

środa, 24 lipca 2013

[Visual Studio] Unit Testy

Pisząc Unit Testy należy pamiętać o zasadzie 3xA: Arrange Act Assert. Oznacza ona, że metody testujące powinny składać się z pewnego szablonu: na początku przypisujemy zmienne i oczekiwane wyjście, później wykonujemy test, a na końcu sprawdzamy, czy wynik jest poprawny. Wygodnym Frameworkiem do pisania Unit Testów w VS jest NUnitFramework. Instalujemy go za pomocą NuGeta.


Przykładowa metoda do przetestowania:

public class StringHelper
{
    public static int CountLetters(string word, char letter)
    {
        return word.Count(c => c == letter);
    }
}

...i odpowiadający mu UnitTest.

[TestFixture]
public class StringHelperTest
{
    [Test]
    public void CountLettersTest()
    {
        //Arrange
        var @string = "copacabana";
        var letter = 'a';
        int expected = 4;

        //Act
        int current = StringHelper.CountLetters(@string, letter);

        //Assert
        Assert.AreEqual(expected, current);
    }
}

Dla klas i metod obowiązuje pewna konwencja dodawania na końcu nazw słowa Test. Unit Testy można także bez problemu Debugować. Korzystając z dodatku Resharper można uruchamiać pojedyncze testy bezpośrednio w kodzie.


Przydatnymi atrybutami są SetUp i TearDown. Będą to metody wykonywane raz odpowiednio przed i po sesji testów.


[SetUp]
public void Init()
{
    Console.WriteLine("Initializing...");
}

[TearDown]
public void Clean()
{
    Console.WriteLine("Shutting down..."); 
}

Testy można także w razie potrzeby grupować w kategorie, również przez odpowiedni atrybut.

[Test]
[Category("another tests")]
public void CountLettersTest2()
{
    //Arrange
    var @string = "copACABana";
    var letter = 'a';
    int expected = 2;

    //Act
    int current = StringHelper.CountLetters(@string, letter);

    //Assert
    Assert.AreEqual(expected, current);
}

Dzięki temu z poziomu GUI możemy odpalać na przykład tylko testy z danej kategorii.


Ostatnia ciekawa funkcjonalność to timeouty. Możemy ustawić dla danej metody maksymalny czas wykonania poprzez atrybut MaxTime, np. [MaxTime(5000)].

wtorek, 23 lipca 2013

[WPF] Grafika trójwymiarowa

Jedną z ciekawszych funkcjonalności WPF jest wsparcie dla grafiki trójwymiarowej. Funkcjonalności 3D są dostępne zarówno z poziomu XAML jak i kodu proceduralnego. Poniższy kod przedstawia prosty sposób opisu sceny 3D w sposób deklaratywny:


<Window x:Class="_3dGraphics.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Viewport3D>
            <Viewport3D.Camera>
                <OrthographicCamera Position="5,5,5" LookDirection="-1,-1,-1" Width="5"/>
            </Viewport3D.Camera>
            <Viewport3D.Children>
                <ModelVisual3D x:Name="Light">
                    <ModelVisual3D.Content>
                        <AmbientLight/>
                    </ModelVisual3D.Content>
                </ModelVisual3D>
                <ModelVisual3D>
                    <ModelVisual3D.Content>
                        <Model3DGroup x:Name="House">
                            <GeometryModel3D x:Name="Roof">
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial Brush="Blue"/>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D Positions="-1,1,1 0,2,1 0,2,-1 -1,1,-1 0,2,1 1,1,1
      1,1,-1 0,2,-1"
      TriangleIndices="0 1 2 0 2 3 4 5 6 4 6 7"/>
                                </GeometryModel3D.Geometry>
                            </GeometryModel3D>
                            <GeometryModel3D x:Name="Sides">
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial Brush="Green"/>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D Positions="-1,1,1 -1,1,-1 -1,-1,-1 -1,-1,1 1,1,-1
       1,1,1 1,-1,1 1,-1,-1"
       TriangleIndices="0 1 2 0 2 3 4 5 6 4 6 7"/>
                                </GeometryModel3D.Geometry>
                            </GeometryModel3D>
                            <GeometryModel3D x:Name="Ends">
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial Brush="Red"/>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D
       Positions="-0.25,0,1 -1,1,1 -1,-1,1 -0.25,-1,1 -0.25,0,1
       -1,-1,1 0.25,0,1 1,-1,1 1,1,1 0.25,0,1 0.25,-1,1 1,-1,1
       1,1,1 0,2,1 -1,1,1 -1,1,1 -0.25,0,1 0.25,0,1 1,1,1 1,1,-1
       1,-1,-1 -1,-1,-1 -1,1,-1 1,1,-1 -1,1,-1 0,2,-1"
       TriangleIndices="0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 15
       17 18 19 20 21 19 21 22 23 24 25"/>
                                </GeometryModel3D.Geometry>
                            </GeometryModel3D>
                        </Model3DGroup>
                    </ModelVisual3D.Content>
                </ModelVisual3D>
            </Viewport3D.Children>
        </Viewport3D>
    </Grid>
</Window>

Zastosowane powyżej elementy XAML służą do:

  • GeometryModel3D - reprezentuje kształt i materiał obiektu 3D, kształt w powyższym przypadku jest siatką, w której podaje się współrzędne trójkątów oraz ich indeksy.
  • ModelVisual3D - odpowiada za renderowanie contentu 3D
Położenie kamery oraz obiektów na scenie podaje się, pamiętając o układzie osi w kartezjańskim układzie współrzędnych.
Układ współrzędnych jest prawoskrętny, a pozycję podaje się ustawiając wartości na atrybucie Position.
Pozostałe ważne atrybuty to LookDirection (kierunek, w którym ma być obrócona kamera), oraz UpDirection decydujący o obrocie kamery wokół osi z. 

Rodzaje kamer:
  • PerspectiveCamera - odpowiada postrzeganiu przestrzeni przez ludzkie oko, obiekty znajdujące się daleko od kamery wydają się mniejsze, niż te bliższe
  • OrthographicCamera - obiekty pozostają tej samej wielkości niezależnie od odległości
Szerokość pola widzenia kontrolowana jest przez atrybut Width (dla drugiej kamery) i przez atrybut FieldOfView (dla pierwszej kamery).

Transformacje 3D:

Poniżej przedstawiono, jak wykonać trzy podstawowe transformacje z poziomu kodu proceduralnego


private void KeyDownHandler(object sender, KeyEventArgs e)
{
    Transform3DGroup group = new Transform3DGroup();
    switch (e.Key)
    {
        case Key.T:
            TranslateTransform3D transform3D = new TranslateTransform3D(0.1,0,0);
            group.Children.Add(transform3D);
            House.Transform = group;
            break;
        case Key.R:
            //45 - stopnie, nie radiany, new Vector3D(0, 1, 0) - wokol jakiej osi obrot
            RotateTransform3D rotate3d = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 1, 0), 45));
            group.Children.Add(rotate3d);
            House.Transform = group;
            break;
        case Key.S:
            ScaleTransform3D scale3d = new ScaleTransform3D(0.5,0.5,1);
            group.Children.Add(scale3d);
            House.Transform = group;
            break;
        default:
            break;
    }
}

Rodzaje świateł:

  • DirectionalLight - wysyła równoległe wiązki światła ze źródła umieszczonego nieskończenie daleko, odpowiada słońcu
  • PointLight - odpowiada żarówce, wysyła światło we wszystkich kierunkach, intensywność spada wraz ze wzrostem odległości od źródła
  • FlashLight - odpowiada działaniu latarki, emituje stożek światła, którego intensywność spada wraz ze wzrostem odległości od źródła
  • AmbientLight - światło rozproszone