Archiv der Kategorie ‘.NET‘

 
 

Resharper 5: Verlängerte 60-Tage-Testlizenz + 10% Rabatt auf Lizenzerwerb

Hallo, ich komm gleich zur Sache: Resharper ist cool. Wer das noch nicht weiß, sollte sich unbedingt einmal die Testversion des Visual-Studio-Addins herunterladen und einfach mal ausprobieren.

Das blöde für Hobby-Programmierer (bzw. für Entwickler die auch nebenberuflich programmieren, aber nicht unbedingt komerziell) ist allerdings, dass Resharper auch nicht ganz billig ist. Eine Personal Licence kostet immerhin 188 €. Wer also das Addin noch etwas länger testen möchte, der kann einen kostenlosen 60-Tage-Testlizenzschlüssel erhalten.
Dazu muss man einfach eine Anfrage an David Ridgway (Details siehe Blog) stellen und man erhält per E-Mail einen persönlichen Lizenzschlüssel und zusätzlich noch einen 10%-Rabatt-Code, falls man sich dazu entschließt, Resharper anschließend zu kaufen. Finde ich persönlich eine prima Sache! :)

P.S.: Wer ganz schlau ist, reizt erst die Standard-30-Tage-Testversion von Resharper 5 aus und gibt anschließend den 60-Tage-Lizenzschlüssel ein. So schafft man es immer hin auf 90 Tage Testzeitraum. ;)

Update vom 03.06.2010: Das Angebot von Jetbrains ist leider nicht mehr gültig. :(

DelegateBinder – DataBinding mit Datenmanipulation

Ich hatte mal irgendwann vor längerer Zeit die Idee, eine Klasse zu programmieren, mit der ich einfache GUI-Logik leicht implementieren kann, ohne unnötigen Code schreiben zu müssen. Ziel war es, Dinge wie z.B. “Aktiviere einen Button nur, wenn eine gültige/vorhandene Datei in einer TextBox eingegeben wurde” oder “Deaktiviere andere Controls, wenn eine CheckBox angehakt ist” und sonstige kleine Spielereien die man dann und wann in der GUI-Programmierung braucht, zu vereinfachen.
Bisher musste ich sowas immer auf die Weise erledigen, dass ich (im Falle des ersten Beispiels) eine Methode programmiert habe, die über die File.Exists-Methode geprüft hat, ob der String in der TextBox auf eine gültige Datei verweist. Anschließend musste ich das TextChanged-Ereignis an die Methode hängen, damit die Prüfung erneut ausgeführt wird, wenn der Benutzer den Text ändert. Das funktioniert zwar und ist nicht allzu schwer in der Umsetzung, der Designer nimmt einem den nervigen Event-Kram ja ab, aber was ich bei dieser Lösung unschön finde, ist, für einen Einzeiler extra eine Methode schreiben zu müssen. Also hab ich mich hingesetzt und mir eine Lösung überlegt, und rausgekommen ist der DelegateBinder.

Vorab schon einmal der C#-Code der Klasse:

using System;
using System.ComponentModel;
using System.Windows.Forms;

[ToolboxItem(false)]
public class DelegateBinder : Control
{
    public delegate object BindingDelegate(object value);

    private BindingDelegate _bindingDelegate;
    private object _bindingProperty;

    public object BindingProperty
    {
        get { return _bindingProperty; }
        set { _bindingProperty = _bindingDelegate(value); }
    }

    private DelegateBinder(BindingDelegate bindingDelegate)
    {
        _bindingDelegate = bindingDelegate;
    }

    public static void Bind(BindingDelegate bindingDelegate, Control target, string propertyName, object dataSource, string dataMember)
    {
        if (bindingDelegate == null)
            throw new ArgumentNullException("bindingDelegate");

        if (target == null)
            throw new ArgumentNullException("target");

        if (dataSource == null)
            throw new ArgumentNullException("dataSource");

        var binder = new DelegateBinder(bindingDelegate);
        target.Controls.Add(binder);
        binder.DataBindings.Add("BindingProperty", dataSource, dataMember);
        target.DataBindings.Add(propertyName, binder, "BindingProperty");
    }
}

Funktionsweise
Die Klasse DelegateBinder hat eine statische Methode Bind, die als Parameter einen Delegaten – der einen Object-Parameter erwartet und ein Object zurückgibt – und eine Referenz auf das Zielobjekt (das Control, dem das Binding hinzugefügt werden soll) empfängt. Weiterhin übergibt man der Bind-Methode wie beim normalen DataBinding-Konstruktor die Parameter für propertyName, dataSource und dataMember.
Der Trick bei dieser ganzen Sache ist nun folgender: In der Bind-Methode wird ein neues DelegateBinder-Objekt erzeugt. Das Objekt hat eine Eigenschaft BindingProperty, an welche ich den Member der DataSource (also die Eigenschaft des Objekts, von dem die Daten kommen) binde. Nun dreh ich den Spieß um und binde die BindingProperty dieses Objekts an das Ziel-Objekt, das die (veränderten) Daten enthält. Das eigentliche Konvertieren/Bearbeiten der Daten erfolgt durch den Delegaten, den man der Bind-Methode übergibt. Dieser wird im Setter der BindingProperty aufgerufen, also immer dann, wenn sich die Daten vom Control (oder welches Objekt auch immer) geändert haben. In dem Moment, in dem nun der Wert der Eigenschaft BindingProperty geändert wird, schlägt das DataBinding des eigentlichen Ziel-Controls/Objekts zu, das ja an das DelegateBinder-Objekt gebunden ist und erhält den nun geänderten Wert. Die eigentliche Datenmanipulation findet daher über den “Zwischenmann” statt, der zwischen der DataSource und dem eigentlichen Target zwischengeschaltet ist.

Anwendung
Die Beispiele von oben würde man folgendermaßen umsetzen:

DelegateBinder.Bind(x => File.Exists((string)x), button1, "Enabled", textBox1, "Text");
DelegateBinder.Bind(x => !(bool)x, textBox2, "Enabled", checkBox1, "Checked");
DelegateBinder.Bind(x => !(bool)x, listView1, "Enabled", checkBox1, "Checked");

Im angehängten Beispielprojekt sieht man das ganze in einem WinForms-Projekt in Aktion.

DelegateBinderSampleProject

Disposable TemporaryFile

Wenn man in einem Programm mit temporären Dateien arbeitet, gehört es normalerweise zum guten Ton, diese anschließend wieder aus dem Temp-Verzeichnis des Benutzers zu löschen, um die Festplatte nicht zuzumüllen.
Das ist natürlich in einem gewissen Grad für den Programmierer nervig. Als ich einen entsprechenden Anwendungfall hatte, habe ich mir gedacht, das muss auch irgendwie eleganter und einfacher gehen. Das hat mich schließlich auf die Idee gebracht, eine kleine Klasse zu programmieren, die mir den ganzen Nebenkram des Dateihandlings – erstellen und wieder löschen der physikalischen Datei – abnimmt. Hierfür hat sich das Dispose Pattern angeboten, das man in .NET über das IDisposable-Interface implementieren kann.

Herausgekommen ist eine kleine aber feine Klasse:

using System;
using System.IO;

public sealed class TemporaryFile : IDisposable
{
    private bool disposed;

    public string FilePath { get; private set; }

    public TemporaryFile()
    {
        FilePath = Path.GetTempFileName();
    }

    ~TemporaryFile()
    {
        Dispose(false);
    }

    #region Dispose Pattern Implementation

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (disposed)
            return;

        if (File.Exists(FilePath))
            File.Delete(FilePath);

        disposed = true;
    }

    #endregion
}

Jetzt ist es ganz bequem möglich, eine temporäre Datei in einem using-Block zu verwenden. Sobald das Ende des Codeblocks erreicht ist, wird die Datei automatisch wieder gelöscht:

using (var file1 = new TemporaryFile())
{
    Console.WriteLine(file1.FilePath);
    // Sonstige Arbeiten an der temporären Datei
}