2 Stimmen

Generische Schnittstelle als Methodenparameter und sehende Felder

Das ist wahrscheinlich meine Naivität, die durchscheint, aber egal...

Ich habe eine generische Schnittstelle, die eine Reihe von Standardmethoden (unterschiedlich implementiert) für verschiedene Implementierungen definiert.

Ich übergebe die Schnittstelle als Parameter an eine Methode, die für die Speicherung in einer Datenbank zuständig ist. Ich habe z.B. einige Implementierungen namens Bug, Incident usw., die von der generischen Schnittstelle (genannt IEntry) definiert werden. Diese konzertierten Implementierungen verwenden auch IEnumerable

Da ein Fehler etwas anderes ist als ein Vorfall, gibt es verschiedene Felder. Wenn ich die Schnittstelle als Parameter an eine Methode übergebe, gibt es dann eine Möglichkeit, auf den Typ zu schließen? Wenn ich also das Bug-Objekt übergebe, kann ich seine Felder verwenden, die nicht dieselben sind wie die Felder von Incident. Diese Felder sind für die Persistenz in der Datenbank nützlich. Ich gehe davon aus, dass dies nicht der Fall ist, weil es keine Möglichkeit gibt, den Typ des übergebenen Objekts zu kennen (offensichtlich), aber ich weiß, dass die Leute hier mehr Wissen haben. Gibt es in diesem Fall einen besseren Weg, die Dinge zu tun? Wegen der Ähnlichkeit würde ich gerne bei den Schnittstellen bleiben.

EDIT: Ich schätze, die andere Möglichkeit ist, einige Flusssteuerung verwenden, um die Sql-Anweisung on the fly zu generieren und dann als Parameter übergeben.

Gracias

3voto

Lasse V. Karlsen Punkte 364542

Die Sache mit der Übergabe von Objekten und Schnittstellen ist, dass man sich nicht um den tatsächlichen Typ kümmern sollte, solange er von der jeweiligen Basisklasse/Schnittstelle, an der man interessiert ist, erbt/implementiert.

Logik in die Methode einzubauen, um herauszufinden, dass es sich um einen Fehler handelt, und dann auf Dinge zuzugreifen, die nur bei Fehlern vorhanden sind, ist also im Grunde nicht der OOP-Weg, obwohl es in Ihrem speziellen Fall der "beste" Weg sein könnte.

Ich würde jedoch davon abraten und stattdessen versuchen, eine richtige OOP-Methode mit Polymorphismus zu entwickeln, um die Unterschiede zu behandeln, anstatt sie als Sonderfälle in die Methode einzubauen.

Sie erwähnen Persistenz, ist diese Methode verantwortlich für die Speicherung der Daten irgendwo? Vielleicht könnten Sie den Teil, der die zu speichernden Informationen sammelt, von dem Teil trennen, der die Informationen speichert. Auf diese Weise könnten Sie das Objekt selbst bitten, Ihnen alle relevanten Informationen zu liefern, die von einer Klasse zur anderen variieren können.

3voto

Llyle Punkte 5810

Schlechtes Design (wie ich glaube, in der Frage beschrieben):

public interface IEntry
{
    string Description { get; set; }
}
public class Bug : IEntry
{
    public int ID { get; set; }
    public string Description { get; set; }
    public string UserName { get; set; }
}
public class Incident : IEntry
{
    public Guid ID { get; set; }
    public string Description { get; set; }
}

public class Persister
{
    public void Save(IEnumerable<IEntry> values)
    {
        foreach (IEntry value in values) { Save(value); }
    }

    public void Save(IEntry value)
    {
        if (value is Bug) { /* Bug save logic */ }
        else if (value is Incident) { /* Incident save logic */ }
    }
}

Verbesserte Gestaltung (Smart-Entity-Ansatz):

public interface IEntry
{
    string Description { get; set; }
    void Save(IPersister gateway);
}

public class Bug : IEntry
{
    public int ID { get; set; }
    public string Description { get; set; }
    public string UserName { get; set; }

    public void Save(IPersister gateway)
    {
        gateway.SaveBug(this);
    }
}

public class Incident : IEntry
{
    public Guid ID { get; set; }
    public string Description { get; set; }

    public void Save(IPersister gateway)
    {
        gateway.SaveIncident(this);
    }
}

public interface IPersister
{
    void SaveBug(Bug value);
    void SaveIncident(Incident value);
}

public class Persister : IPersister
{
    public void Save(IEnumerable<IEntry> values)
    {
        foreach (IEntry value in values) { Save(value); }
    }

    public void Save(IEntry value)
    {
        value.Save(this);
    }

    public void SaveBug(Bug value)
    {
        // Bug save logic
    }

    public void SaveIncident(Incident value)
    {
        // Incident save logic
    }
}

Das verbesserte Design ist nur für die Notwendigkeit, die Notwendigkeit der Änderung von Persister.Save(IEntry) zu verschieben. Ich wollte nur einen ersten Schritt aufzeigen, um den Code weniger spröde zu machen. In der Realität und im Produktionscode würden Sie eine BugPersister- und eine IncidentPersister-Klasse haben wollen, um die Anforderungen der Grundsatz der einzigen Verantwortung .

Ich hoffe, dass dieses eher auf den Code bezogene Beispiel eine Hilfe ist.

0voto

GurdeepS Punkte 61489

Bei der Persistenz handelt es sich lediglich um eine Methode in einer Klasse zum Hochladen von Details in eine Datenbank.

Ich schätze, ich könnte eine abstrakte Klasse mit einer Funktion für die Persistenz-Anforderung schreiben und das könnte auf Parameter basieren, damit es funktioniert. Ich kann dies in jeder meiner Schnittstellenimplementierungen verwenden. Da die Art und Weise die Aktualisierung zu db passieren wird (ziemlich viel die gleichen, aber ein paar Worte in einer SQL-Abfrage ändern), kann ich diese auf Basis von Methodenparametern generieren.

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