Object Browser for Windows Phone

november 6, 2011 Szóljon hozzá most!

Minden .NET fejlesztő számára egy “Must have” alkalmazás: Object Browser for Windows Phone. A Compact Framework BCL-jében lévő névtereket, típusokat és tagjaikat tudjátok vele böngészni a telefonotokon.

http://www.windowsphone.com/hu-HU/apps/9b3212b4-aafc-42c8-8e7a-0e17753b9a2a

Object Browser - Namespaces

Namespaces

Object Browser - Classes

Classes

Object Browser - Member Info

Member Info

Object Browser - Search

Search

Kategóriák:Uncategorized Címkék:

Ini Language Service for Visual Studio 2010

április 3, 2011 Szóljon hozzá most!

Idén úgy döntöttem, hogy a saját kódszerkesztőm írása helyett inkább a Visual Studio SDK-val kezdek el foglalkozni. Kezdésképpen a hétvégén összeraktam egy egyszerű kis nyelvi szolgáltatást ini fájlok kezeléséhez. Így mostantól aki ini fájlokat szeretne szerkesztgetni Visual Studioban a megszokott Developer Experience-szel, az megteheti. :)

Ini Language Service for Visual Studio 2010

Ini Language Service for Visual Studio 2010

Letöltés: http://visualstudiogallery.msdn.microsoft.com/0d9e83c9-4ab9-4091-8eed-11db852d5992

Hyperoperations

november 7, 2010 Szóljon hozzá most!

Egy művelet mindenek felett… Picit átevezve az absztrakt matematika és csoport elmélet vizeire, most ne csak osztályokat származtassunk, hanem műveleteket is. Legyen a nulladik hiperművelet az értéknövelés egységgel. Ebből már eljuthatunk az összeadásig (valahány darab értéknövelés), a szorzásig (valahány darab összeadás), a hatványozásig (valahány darab szorzás), a tetrációig (valahány darab hatvány)… és még végtelen sokadfokú művelethez (egyelőre ugyan csak a természetes számok körében).

F# megvalósítás:

let rec hyper (left : int) (op : int) (right : int) : int =
    match (op, right) with
    | (0, _) -> right + 1
    | (1, 0) -> left
    | (2, 0) -> 0
    | (3, 0) -> 1
    | _ -> hyper left (op - 1) (hyper left op (right - 1))

Legyen left az első, right a második operandus, op pedig a művelet fokszáma (összeadás: 1, szorzás: 2, …).

Példa:

let additionExample = hyper 2 1 3 // 5
let multipliationExample = hyper 2 2 3 // 6
let exponentiationExample = hyper 2 4 3 // 8
let tetrationExample = hyper 2 4 3 // 16

Ez a rekurzív megvalósítás egy hatalmas, már nem elfogadható kompromisszum, de szép. :) Teljesen absztrakt, viszont csak nagyon kis számokkal tud dolgozni, mert különben szembekerülünk egy hatalmas StackOverflowExceptionnel.

A C# implementációt innen töltheted le.

Dynamic UI: Import and export data

július 26, 2010 Szóljon hozzá most!

Fejtegessük tovább a témát, az önmagát generáló felhasználói felületet. Most az adatok exportálására fogunk fókuszálni. Ugyanazt az adatot több féle formátumban, több féle szabvány szerint is menthetjük és ahhoz, hogy ezt megvalósítsuk, különböző exportáló osztályokat kell megírnunk.

A felhasználói felületen ezek az osztályok egy mentés ablakon keresztül kapnak szerepet. Ott kell kilistáznunk az elérhető formátumokat és a felhasználó döntése szerint létrehozni a megfelelő osztályból egy példányt az adatok mentésére. Célunk ennek a teljes folyamatnak az automatizálása.

Kezdjük is az exportáló osztályokkal:

public abstract class ReportExporter : IDisposable { }

public class CsvReportExporter : ReportExporter { }

public class XmlReportExporter : ReportExporter { }

A legjobb megoldás a metaadatok tárolására az attribútumok használata. A miénk legyen a ReportExporterDescriptionAttribute. Két tulajdonságot kell tartalmaznia: FormatDisplayName és FileExtension. Alkalmazzuk ezt az attribútumot a meglévő osztályokra:

[ReportExporterDescription(FormatDisplayName = "Comma Separated Values", FileExtension = ".csv")]
public class CsvReportExporter : ReportExporter
{ }

Mostantól megvannak a megfelelő osztályaink ellátva a szükséges metaadatokkal. A következő lépés, hogy életre keltsük a felhasználói felületet. A .NET Framework Reflection képességét fogjuk használni, hogy kinyerjük az adott assemblynkből az összes olyan osztályt, amely a ReportExporter osztályból származik.

public void ExportReport()
{
    // Get exporters using reflection
    Type[] exporters = typeof(ReportExporter).Assembly.GetTypes().Where(
        t => t.IsSubclassOf(typeof(ReportExporter))
    ).ToArray();

    // Show save file dialog with the available filters
    using (SaveFileDialog sfd = new SaveFileDialog() {
        Filter = String.Join(
            "|", exporters.Select(t => {
                ReportExporterDescriptionAttribute attr =
                    (ReportExporterDescriptionAttribute)t.GetCustomAttributes(
                        typeof(ReportExporterDescriptionAttribute), false
                    ).First();
                return String.Format("{0} (*{1})|*{1}", attr.FormatDisplayName, attr.FileExtension);
            }).ToArray()
        )
    })
    {
        if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            // Create a ReportExporter instance and render the contents
            using (ReportExporter exporter = Activator.CreateInstance(
                exporters[sfd.FilterIndex - 1], sfd.FileName
            ) as ReportExporter)
                exporter.Render(this.Report);
        }
    }
}

Így ha később változtatunk a kódon és kiegészítjük egy új formátum kezelésére képes osztállyal, amit ellátunk a megfelelő attribútumokkal, akkor sehol máshol nem kell módosítanunk, mert az imént megírt metódus tökéletesen idomulni fog a változásokhoz.

Kategóriák:Development Címkék:, , ,

Dynamic UI: Filtering

július 22, 2010 Szóljon hozzá most!

Egy magas minőségű üzleti alkalmazásnál a felhasználói felületnek is dinamikusnak, jól tesztelhetőnek kell lennie. Jelen esetben Windows Forms környezetet fogunk használni és most példaképpen egy tetszőleges lista szűrését szeretném bemutatni kivezetve a felhasználói felületre, amelyet automatikusan építünk fel.

A lista szűrése

Van egy kollekciónk, amiből készítünk egy nézetet. Ezt a nézetet szeretnénk megszűrni tekintet nélkül a típusra és a szűrendő tulajdonság nevére, típusára.

public void FilterView<T, TProperty>(IList<T> view, string propertyName, TProperty value)
{
    foreach (T e in view)
        if (typeof(T).GetProperty(propertyName).GetValue(e, null).Equals(value))
            view.Remove(e);
}

Menüelemek generálásának automatizálása

Tegyük fel, hogy egy olyan tulajdonságra szeretnénk szűrni, amelynek véges számú értéke lehet. Erre a legcélszerűbb típus az enum. A felhasználói felületen ezt egy ToolStrip-en szeretnénk megjeleníteni, minden egyes menünek megfeleltetve egy-egy értéket. A menüket be- illetve kipipálva szűrheti a listát a felhasználó. Az alábbi metódus ezt a feladatot teljes mértékben automatizálja. Legenerálja a menüket és egyúttal teljesen működőképessé teszi őket.

public static void PopulateEnumFilterMenu<T, TProperty>(
    this ToolStripMenuItem menu,
    TProperty options, string propertyName, IList<T> view, TProperty except = null
) where TProperty : enum // hátha a .net 5 majd elhozza ezt : )
{
    foreach (TProperty p in Enum.GetValues(typeof(TProperty)))
    {
        if (p.Equals(except))
            continue;

        menu.DropDownItems.Add(
            new ToolStripMenuItem(
                p.ToString(), null, (s, e) => {
                    this.FilterReport<T, TProperty>(
                        view, propertyName, (TProperty)(s as ToolStripMenuItem).Tag
                    );
                }
            ) { Tag = p, Checked = true, CheckOnClick = true }
        );
    }
}

Az except paraméter egy kivételt enged meg, amely nem kerül kivezetésre a felületre. Ennek oka az, hogy az irányelvek szerint az enum-oknak tartalmazni kell egy None = 0 értéket is. Ez a paraméter ennek az átugrását hivatott kezelni, ha erre szükség van.

Ezáltal kaptunk egy dinamikus szűrési mechanizmust, amely független a szűrendő kollekcióban lévő elemek típusától, a szűrt tulajdonságtól, a kollekciót prezentáló vezérlőtől, ad egy szintén dinamikus felhasználói felületet a szűréshez és fel van készítve teljes mértékben a kód megváltoztatására, kibővítésére.

LINQ and Frequency Analysis

február 6, 2010 Szóljon hozzá most!

Mindenek előtt szükségünk lesz egy olyan metódusra, ami tud mindent, de mégsem csinál semmi konkrétat. A GroupAndSelect képes csoportosítani egy kollekció elemeit selector szerint, transzformálni a kapott csoportokat resultSelector szerint és visszaadni mindezt egy KeyValuePair kollekcióként.

public static IEnumerable<KeyValuePair<TKey, TResult>> GroupAndSelect<TSource, TKey, TResult>(
    this IEnumerable<TSource> collection,
    Func<TSource, TKey> selector,
    Func<IGrouping<TKey, TSource>, TResult> resultSelector
)
{
    return from i in collection
           group i by selector(i) into g
           select new KeyValuePair<TKey, TResult>(g.Key, resultSelector(g));
}

public static IEnumerable<KeyValuePair<TSource, TResult>> GroupAndSelect<TSource, TResult>(
    this IEnumerable<TSource> collection,
    Func<IGrouping<TSource, TSource>, TResult> resultSelector
)
{
    return collection.GroupAndSelect(i => i, resultSelector);
}

Most használjuk is ki ezt arra, hogy megkeressük melyik elem, pontosan hányszor fordul elő az adott kollekcióban. Csoportosítunk, majd kiválasztjuk a csoportokban szereplő elemek számát.

public static IEnumerable<KeyValuePair<TKey, int>> ItemFrequencies<TSource, TKey>(
    this IEnumerable<TSource> collection, Func<TSource, TKey> selector
)
{
    return collection.GroupAndSelect(selector, g => g.Count());
}

Még egy egyszerűsített változat, hogy könnyen használható legyen:

public static IEnumerable<KeyValuePair<TSource, int>> ItemFrequencies<TSource>(
    this IEnumerable<TSource> collection
)
{
    return collection.ItemFrequencies(i => i);
}

Néhány példa:

Számok csoportosítása maradékosztályok szerint:

new int[] { 2, 4, 3, 8, 12, 9, 5, 7 }.ItemFrequencies(i => i % n);

Frekvenciaelemzés kriptoanalízishez:

"The quick brown fox".Where(c => Char.IsLetter(c)).ItemFrequencies()
Kategóriák:Development Címkék:, , , ,

LINQ and Factorial

február 2, 2010 Szóljon hozzá most!

A LINQ akkor is barátunk, ha faktoriálist szeretnénk számolni, mindössze egyetlen sorból. :) Egyszerűen csak legyártjuk a számokat, majd összefűzzük őket a szorzás művelettel.

Func<int, int> Factorial = n => Enumerable.Range(1, n).Aggregate(1, (x, i) => x * i);

Bónuszként egy F# implementáció rekurzív módon:

let rec Factorial n =
    match n with
    | 0I -> 1I
    | _ -> n * Factorial(n - 1I)

Mindkét módszer 0-ra 1-et ad eredményül.

Kategóriák:Development, Mathematics Címkék:, , , ,

LINQ and Prime Numbers

január 28, 2010 Szóljon hozzá most!

Mire képes a LINQ… Fibonacci után most itt vannak a prímszámok.

Func<int, int, IEnumerable<int>> GetPrimes = (min, max) =>
    from n in Enumerable.Range(min, max - min)
    where Enumerable.Range(2, n / 2).All(i => n % i != 0)
    select n
;

Nyilván lehetne gyorsítani közel annyi féle módon, ahány prímszám van, de ezt természetesen nem a teljesítménye miatt tettem közzé.

Egy sorból: Számológép

január 19, 2010 Szóljon hozzá most!

Gyerekkori találmányom, az (valóban) egy soros számológép, amely figyelembe veszi a műveletek sorrendjét, kezeli a tört számokat a függvényeket és sok más egyebet… :) Gondoltam megosztom:

JavaScript nyelven:

alert("Result: " + eval(prompt("Expression:")));

VBScript nyelven:

MsgBox("Result: " + Eval(InputBox("Expression:")));

A VBS verzióban még a hatvány operátor is használható! :P

A kód minőségétől, biztonságától, tervezettségétől stb stb… most az egyszer tekintsünk el. :)

Kategóriák:Development Címkék:, ,

Egy sorból: E-mail küldés

január 17, 2010 Szóljon hozzá most!

Az "Egy sorból" című induló rovatban hasonló kódokat fogtok találni, mint ez. A kérdés: mi mindent lehet kihozni egyetlen sornyi kódból…

new SmtpClient(serverAddress, 465) {
    EnableSsl = true,
    UseDefaultCredentials = false,
    Credentials = new NetworkCredential(username, password)
}.Send(
    new MailMessage(
        new MailAddress(toAddress, String.Format("{0} <{1}>", toName, toAddress)),
        new MailAddress(senderAddress, senderName)
    ) {
        Subject = subject,
        Body = messageBody,
        SubjectEncoding = System.Text.Encoding.UTF8,
        BodyEncoding = System.Text.Encoding.UTF8,
        IsBodyHtml = true
    }
);
Kategóriák:Development Címkék:, ,
Follow

Get every new post delivered to your Inbox.