2 Stimmen

ASP.NET: Speichern von Klasseneigenschaften in der Sitzung und Verwendung eines Sitzungshandlers - ist das ein gutes Design?

Ich habe eine Klasse namens EditMapUtilities.

Hier sind einige Klasseneigenschaften, die ich beibehalten möchte:

public class EditMapUtlities
{
    public static Boolean isInitialEditMapPageLoad
    {
        get { return SessionHandler.isInitialEditMapPageLoad; }
        set { SessionHandler.isInitialEditMapPageLoad = value; }
    }

// REST OF CLASS NOT GERMAIN TO DISCUSSION AND OMITTED
}

Hier ist meine SessionHandler-Klasse, die dem Muster aus diesem Beitrag folgt Statische Sitzungsklasse und mehrere Benutzer :

using System.Web.SessionState;

public static class SessionHandler
{
    private static HttpSessionState currentSession
    {
        get
        {
            if (HttpContext.Current.Session == null)
                throw new Exception("Session is not available in the current context.");
            else
                return HttpContext.Current.Session;
        }
    }

    //A boolean type session variable
    private static string _isInitialEditMapPageLoad = "EditMapInitialPageLoad";
    public static bool isInitialEditMapPageLoad
    {
        get 
        {
            if (currentSession[_isInitialEditMapPageLoad] == null)
                return true;
            else
                return (Boolean)currentSession[_isInitialEditMapPageLoad];    
        }
        set
        {
            currentSession[_isInitialEditMapPageLoad] = value;
        }
    }
}

Ich bin noch dabei, OOAD zu lernen. Ich möchte relevante Eigenschaften mit relevanten Klassen behalten. Außerdem möchte ich alle gespeicherten Sitzungsvariablen an einem Ort aufbewahren, um die Wartung zu erleichtern und die Sitzungsschlüssel und -aufrufe zu kapseln.

Ich habe allerdings das Gefühl, dass mein Entwurf zu sehr gekoppelt ist. Wie kann ich es mehr lose gekoppelt machen? Ist meine editMapUtilities Klasse zu eng an die SessionHandler Klasse gekoppelt? Wie würden Sie es besser machen?

5voto

Josh Punkte 44274

Ihre Intuition ist ziemlich gut, denn Ihre Klassen sind in der Tat sehr eng aneinander gekoppelt. Ich beziehe mich auf Bob Martins Grundsätze des objektorientierten Designs .

Nach der Prinzip der einzigen Verantwortung Sie möchten sicherstellen, dass Sie nicht beide Klassen aktualisieren müssen, wenn sich eine von ihnen ändert. Im Moment wissen beide Klassen ein wenig zu viel übereinander.

Wir können beginnen mit EditMapUtilites und den Zugriff auf den Sitzungshandler umgestalten, um die Absicht besser zu vermitteln. Vor allem der Anwendungsstatus ist auf den Benutzer beschränkt. Wir können auch ändern, wie wir auf diese Werte zugreifen, um die Kopplung zu verringern, indem wir Methoden verwenden, die das gleiche Ziel erreichen.

public class EditMapUtlities
{
    //Omitting the wireup details for now
    private SessionHandler ApplicationState {get; set;}

    public static Boolean isInitialEditMapPageLoad
    {
        get { return ApplicationState.GetValue<Boolean>("EditMapInitialPageLoad"); }
        set { ApplicationState.SetValue("EditMapInitialPageLoad", value); }
    }

// REST OF CLASS NOT GERMAIN TO DISCUSSION AND OMITTED
}

Und die SessionHandler Klasse würde nun zwei neue Methoden enthalten:

public static T GetValue<T>(String key)
{
    return currentSession[key] ?? default(T);
}

public static void SetValue(String key, Object val)
{
    currentSession[key] = val;
}

Ok, eine Klasse ist jetzt etwas ausführlicher, aber Ihre Sitzungsklasse ist einfacher und flexibler. Das Hinzufügen zusätzlicher Werte ist einfach, aber Sie werden sich vielleicht fragen, warum Sie nicht einfach eine reine Sitzung verwenden?

Der Grund für diese Umstrukturierung der Klassen war, dass wir einen Schritt näher an eine saubere Trennung zwischen ihnen herankommen wollten. Durch den Zugriff auf unsere SessionHandler Klasse über eine Eigenschaft können wir nun einen Schritt weiter gehen und die Prinzip der Inversion von Abhängigkeiten .

Anstatt sich auf eine konkrete Implementierung von SessionHandler Warum abstrahieren wir nicht die Speicherung von Anwendungsstatusvariablen hinter einer Schnittstelle? Eine, die wie folgt aussieht:

public interface IApplicationState
{
    public T GetValue<T>(String key);
    public SetValue(String key, Object val);
}

Jetzt können wir einfach unsere Eigenschaft innerhalb von EditMapUtlities um die Schnittstelle zu verwenden, und übergeben Sie diese durch den Konstruktor unter Verwendung der guten alten manuellen Dependency Injection.

public class EditMapUtlities
{
    //Omitting the wireup details for now
    private IApplicationState ApplicationState {get; set;}

    public EditMapUtilities(IApplicationState appState)
    {
        if(appState == null) throw new ArgumentNullException("appState");

        ApplicationState = appState;
    }

    public static Boolean isInitialEditMapPageLoad
    {
        get { return ApplicationState.GetValue<Boolean>("EditMapInitialPageLoad"); }
        set { ApplicationState.SetValue("EditMapInitialPageLoad", value); }
    }

// REST OF CLASS NOT GERMAIN TO DISCUSSION AND OMITTED
}

Sie können Ihr System leicht überarbeiten SessionHandler Klasse muss die Schnittstelle implementieren und darf nicht statisch sein:

public SessionHandler: IApplicationState { //Implementation }

Wenn Sie die Abwärtskompatibilität mit anderen Bereichen des Codes aufrechterhalten müssen, können Sie eine Wrapper-Klasse erstellen und SessionHandler statisch lassen:

public SessionHandlerWrapper: IApplicationState
{
    //Call SessionHandler from within this class
}

Es stimmt, dass Sie Ihre konkrete Instanz von IApplicationState und übergibt sie an EditMapUtilities aber jetzt ist keine der beiden Klassen von der anderen abhängig. Wenn Sie dies in der Zukunft in der Datenbank speichern wollten, müssten Sie einfach eine neue Klasse schreiben, die IApplicationState . Nur der aufrufende Code müsste geändert werden, um die neue Datenbankklasse anstelle der sitzungsbasierten Klasse zu verwenden.

Jetzt können Sie Ihre neue, lose gekoppelte Architektur und die minimalen Änderungen genießen, die Sie vornehmen müssen, um neue Funktionen hinzuzufügen.

0voto

matt-dot-net Punkte 4206

Daran ist nichts auszusetzen. Machen Sie sich nicht so viele Gedanken über die Kopplung - Klassen müssen genau wie Bausteine zusammenarbeiten. Die Leute machen sich keine Sorgen, wenn ihre Ziegelsteine eng gekoppelt sind. Session und ASP.Net gehen Hand in Hand wie Ziegel und Mörtel. Mit anderen Worten, um eine Webanwendung zu schreiben, muss man HTTP mit Zustandsabhängigkeit versehen.

Ich würde sagen, dass Sie die Sitzung in diesem Fall vielleicht nicht brauchen. Ich neige dazu, den ViewState für Werte zu verwenden, bei denen es mir egal ist, ob der Client sie ändern kann, und die Session für sensiblere Daten (Entity-IDs, rollenbasierte Variablen) zu reservieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X