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

piątek, 2 listopada 2012

[C#|Visual Studio] DefaultValueAttribute

Jednym z atrybutów, jakie udostępnia System.ComponentModel jest DefaultValueAttribute. Wbrew pozorom podanie wartości jako argument konstruktora nie wystarczy, aby ustawić domyślną wartość property. Dokumentacja MSDN jasno mówi, że programista musi sam ustawić domyślne wartości, np. w konstruktorze. Aby wykorzystać możliwości DefaultValueAttribute można skorzystać z mechanizmu reflection.

Zatem poniższy kod, pomimo swojej przejrzystości nie wystarczy, aby ustawić domyślne wartości dla properties.

using System;
using CM = System.ComponentModel;

namespace DefaultValueAttribute
{
    public class MySimpleClass
    {
        [CM.DefaultValue(true)]
        public bool MyBoolProperty { get; set; }

        [CM.DefaultValue(8)]
        public int MyIntProperty { get; set; }

        [CM.DefaultValue("Default text")]
        public string MyStringProperty { get; set; }
    }
}

Aby móc skorzystać z możliwości ustawiania wartości domyślnych poprzez atrybuty, wystarczy skorzystać z poniższej ExtensionMethod.

public static class Extensions
    {
        public static void ApplyDefaultValues(this object obj)
        {
             foreach (CM.PropertyDescriptor prop in CM.TypeDescriptor.GetProperties(obj))
             {
                 var attr = (CM.DefaultValueAttribute) prop.Attributes[typeof (CM.DefaultValueAttribute)];
                 {
                     prop.SetValue(obj, attr.Value);
                 }
             }
        }
    }

Wywoływać ją można np. w konstruktorze.

niedziela, 2 września 2012

[WPF] Dispatcher : opóźnione wykonanie metody

W przypadku, gdy chcemy, aby dispatcher odczekał określony przez nas czas, a następnie wykonał określoną metodę, możemy skorzystać z klasy ThreadPool.

Poniższa ExtensionMethod rozwiązuje problem opóźnionego wywołania dispatchera.


internal static class Extensions
{
    public static void DelayedInvoke(this Dispatcher dispatcher, int delayMs, Action action)
    {
        ThreadPool.QueueUserWorkItem((o) =>
                                            {
                                                Thread.Sleep(delayMs);
                                                dispatcher.Invoke(action);
                                            });
    }
}


czwartek, 5 stycznia 2012

[WPF] Wycinanie z WriteableBitmap

Temat:
Jak wycinać dowolny prostokąt z obrazka reprezentowanego przez WriteableBitmap.

Przygotowałem własną ExtensionMethod dla klasy WriteableBitmap, która korzystając z kodu niezarządzanego wybiera interesujący nas zbiór pikseli i zwraca nową bitmapę. ExtensionMethod działa jako dodatkowa metoda dla istniejącej już klasy. Można jej używać w zasięgu jednego namespace i musi być ona statyczną metoda statycznej klasy przyjmującą za pierwszy argument typ na rzecz którego ma być wywoływana poprzedzony this.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public static class Extensions
    {
        public static WriteableBitmap Split(this WriteableBitmap wb, int left, int top, int width, int height)
        {
            if(left + width > wb.PixelWidth || top + height > wb.PixelHeight)
                throw new ArgumentException("Out of picture bounds !");

            WriteableBitmap split = new WriteableBitmap(width, height, wb.DpiX, wb.DpiY, wb.Format, wb.Palette);

            var pixelLength = wb.Format.BitsPerPixel / 8;
            var stride = pixelLength * wb.PixelWidth;
            var data = new byte[pixelLength * width * height];         
            int k = 0;
                        
            unsafe
            {
                var tab = (byte*)wb.BackBuffer;

                int index = 0;
                for (int j = 0; j < wb.Height; j++)
                {
                    for (int i = 0; i < wb.Width; i++)
                    {

                        if (i > left && i <= left + width && j > top && j <= top + height)
                        {
                            index = j * (pixelLength * (int)wb.PixelWidth) + i * pixelLength;
                            data[k++] = (byte)tab[index];
                            data[k++] = (byte)tab[index + 1];
                            data[k++] = (byte)tab[index + 2];
                            data[k++] = (byte)tab[index + 3];
                        }
                    }
                }
            }


            var rect = new Int32Rect(0, 0, width, height);
            split.WritePixels(rect, data, width * pixelLength , 0);

            return split;
        }
    }

Przykład użycia metody dla obrazka, który jest itemem dodanym do projektu:

1
2
3
4
5
6
7
8
9
private void LoadImage()
        {
            var uri = new Uri("pack://siteoforigin:,,,/vlepa.jpg");
            BitmapSource bs = new BitmapImage(uri);
            image = new WriteableBitmap(bs);

          
            WriteableBitmap small = image.Split(50,50,200,200);
        }

Aby móc kompilować kod niezarządzany (blok unsafe), należy w VS wejść w Properties projektu i w zakładce Build wybrać Allow unsafe code.

Kompilator : VS 2010