Entwickler-Ecke

C# - Die Sprache - Pre- und Post-Funktionen bei Methoden ?


Biplane - Mi 11.11.09 09:38
Titel: Pre- und Post-Funktionen bei Methoden ?
Moinmoin,

in einer Klasse soll bei bestimmten Methoden (siehe "New", "Save") vor und nach der eigentlichen Funktionalität eine andere Methode PreExecute bzw. PostExecute aufgerufen werden. Im Beispiel sieht man was gemeint ist...


C#-Quelltext
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:
class Test

{
    void New()
    {
        if (!PreExecute("New")) return;
        // TODO: Hier eigentliche Implementierung
        PostExevute("New");
    }
    void Save()
    {
        if (!PreExecute("Save")) return;
        // TODO: Hier eigentliche Implementierung
        PostExevute("Save");
    }

    bool PreExecute(string methodeName)
    {

        return true;
    }

    void PostExecute(string methodeName)
    {
    }
}


Diese erste Variante funktioniert einwandfrei, aber ist recht umständlich, da in jeder Methode auf die richtigen Pre- und Post-Aufrufe eingetragen werden müssen.

Variante zwei ist ein anderer Ansatz...



C#-Quelltext
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:
class Test
{
    void New()
    {
        // TODO: Hier eigentliche Implementierung
    }
    void Save()
    {
        // TODO: Hier eigentliche Implementierung
    }

    bool PreExecute(string methodeName)
    {

        return true;
    }

    void PostExecute(string methodeName)
    {
    }

    void Execute(string methodeName)
    {
        if (!PreExecute(methodeName)) return;
        switch (methodeName) // Kann natürlich eleganter mittels Reflection erfolgen
        {
            case "New":
                New();
                break;
            case "Save":
                Save();
                break;
        }
        PostExevute(methodeName);
    }
}


Diese Variante hat den Nachteil, das von aufrufender Stelle immer die Execute-Methode zu verwenden ist. Da die Aufrufe in der Klasse selbst stehen können, wäre somit durch einen direkten Aufruf von "New()", das Pre- und PostExecute zu umgehen.

Gibt es noch eine elegantere Vorgehensweise ?

Idee wäre einfach ein Attribut [PrePostHandling] zu definieren und die Pre- und PostMethode in der Basisklasse würde bei jedem direkten Methode (z.B. "New()") mit diesem Attribut automatisch aufgerufen.


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
class Test : PrePostHandler
{
    [PrePostHandling]
    void New()
    {
        // TODO: Hier eigentliche Implementierung
    }

    [PrePostHandling]
    void Save()
    {
        // TODO: Hier eigentliche Implementierung
    }
}


Aber leider funktioniert das so nicht.

Gruß
Norbert

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt


Christian S. - Mi 11.11.09 10:24

Hallo!

Das wäre wohl ein Fall für apsektorientierte Programmierung. Für C# gibt es da ein paar Frameworks für, da müsstest Du mal googlen, die Namen kenne ich nämlich nicht auswendig. Aber Suche bei Google C# ASPECT ORIENTED FRAMEWORK sollte helfen. Oder Du benutzt Delphi Prism, das hat sowas eingebaut ;-)

Grüße
Christian


Ralf Jansen - Mi 11.11.09 11:35

Im .NET 4.0 werden uns dafür Code Contracts [http://msdn.microsoft.com/en-us/library/dd264808%28VS.100%29.aspx] zur Verfügung stehen.
In früheren .NET Frameworks kannst du auf Spec# [http://research.microsoft.com/en-us/projects/specsharp/] zurückgreifen.


Christian S. - Mi 11.11.09 12:18

Wobei AOP ja noch um einiges mächtiger als Code Contracts ist, bei denen ja "nur" Bedingungen geprüft werden, wenn ich das richtig verstanden habe. Mittels AOP kann man kompletten Code mitsamt Klasse, Interfaces, etc. injizieren.