Pokazywanie postów oznaczonych etykietą dynamic. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą dynamic. Pokaż wszystkie posty

czwartek, 28 lutego 2013

[C#|Visual Studio] C#: Konstrukcja dynamic i ExpandoObject

W języku C# od wersji 4.0 mamy do dyspozycji konstrukcję składniową zaczynającą się od słowa dynamic. Słowo to zapewnia dynamiczną typowalność, to znaczy, że typ takiej zmiennej zostanie ustalony nie na poziomie kompilacji (jak w przypadku słowa var), lecz w czasie pracy programu, stąd owa dynamiczność. Poniżej prosty przykład:

dynamic unknownVariable;
unknownVariable = "this is message";
Console.WriteLine(unknownVariable);
unknownVariable = DateTime.Now;
Console.WriteLine(unknownVariable);

Jeżeli zdarzy nam się, że na przykład do daty z powyższego kodu będziemy chcieli dodać liczbę, co nie jest dozwolonym działaniem, nie otrzymamy błędu kompilacji, ale wyjątek typu RuntimeBinderException, o którym dokumentacja MSDN mówi, że:
Represents an error that occurs when a dynamic bind in the C# runtime binder is processed.
Kolejnym ciekawym typem wykorzystywanym do dynamicznego typowania jest ExpandoObject. Obiekty takie pozwalają na dynamiczne typowanie pól obiektu, co znane jest z innych języków programowania, takich jak np. JavaScript.

dynamic expando = new ExpandoObject();
expando.val1 = "Another silly message";
expando.count = 911;
expando.Pi = 3.14;
foreach (var prop in expando)
{
    Console.WriteLine(prop.GetType());
    Console.WriteLine(prop);
}

Powyższy kod wypisze na konsoli następujące rzeczy:


Zatem widzimy, że ExpandoObject jest odpowiednim słownikiem, umożliwiającym składowanie obiektów dowolnego typu, ze względu na to, że w C# wszystko pochodzi od klasy object.
Aby pobrać pojedynczą wartość, wystarczy zrzutować obiekt dynamicznie typowany do słownika.

var singleValue = ((IDictionary<string, object>) expando)["val1"];

czwartek, 23 sierpnia 2012

[WPF] Logical Resources

Zasobem logicznym może być np. kolor, brush czy czcionka. Mamy do dyspozycji dwa rodzaje zasobów logicznych.

StaticResource -statyczne, ładowane w momencie uruchamiania aplikacji, nie podlegają zmianom w czasie trwania aplikacji, ale też nie wymagają dodatkowych zasobów do śledzenia zmian.

DynamicResource - mogą być zmieniane wielokrotnie w czasie trwania aplikacji, ładowane są dopiero w momencie, kiedy zachodzi taka potrzeba, np. przy wejściu do danej strony.

Na poziomie okna zasoby definiowane są w następujący sposób :

    <Window.Resources>
        <SolidColorBrush x:Key="myBrush" Color="Azure" />
    </Window.Resources>

Mogą być także definiowane na innych poziomach, np. w pliku App.xaml jako zasoby globalne dla całej aplikacji.

   <Application.Resources>
        <ResourceDictionary>
            <SolidColorBrush x:Key="globalBrush" Color="DarkOliveGreen" />
        </ResourceDictionary>
    </Application.Resources>

Do zasobów odwołujemy się w następujący sposób:

<Rectangle Fill="{StaticResource myBrush}" Name="rectangle1" Stroke="Black" VerticalAlignment="Top" Width="491" />
<Rectangle Fill="{DynamicResource globalBrush}"  Name="rectangle2" Stroke="Black" VerticalAlignment="Top" Width="491" />
   

Istnieje możliwość używania tych samych kluczy na różnych poziomach. Podczas wczytywania zasobu, przeszukiwane jest drzewo wizualne, od najbardziej lokalnego poziomu. Jeśli zostanie znaleziony zasób na poziomie okna, to jest on ładowany, jeśli nie, to sprawdzany jest poziom aplikacji, później zasoby systemowe, a gdy również tam nie zostanie nic znalezione, rzucany jest wyjątek.

Warto także pamiętać o tym, że domyślnie, gdy zdefiniujemy zasób i odwołamy się do niego w wielu miejscach, to używana jest jedna instancja. Możemy wymusić tworzenie nowego zasobu poprzez ustawiania atrybutu x:Shared=”False”.

Zasoby można także definiować oraz przydzielać z poziomu Code Behind.


 private void rectangle2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Resources.Add("addedResource", new SolidColorBrush(Colors.Khaki));
            App.Current.Resources.Add("newResource", new SolidColorBrush(Colors.Honeydew));
        }

        private void rectangle1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            ((Rectangle)sender).Fill = (SolidColorBrush)Resources["addedResource"];
            ((Rectangle)sender).Stroke = (SolidColorBrush)App.Current.Resources["newResource"];
        }