it-swarm.com.de

Entwurfsmuster für den Datenimport verschiedener Quelltypen und verschiedener Zieltypen

Ich muss ein Importskript (in C #) entwerfen und erstellen, das Folgendes verarbeiten kann:

  • daten aus verschiedenen Quellen lesen (XML, XSLX, CSV)
  • daten überprüfen
  • schreiben Sie die Daten in verschiedene Objekttypen (Kunde, Adresse)

Die Daten stammen aus einer Reihe von Quellen, aber eine Quelle hat immer ein Importformat (entweder csv, xml, xslx). Importformate können von Quelle zu Quelle variieren. In Zukunft können neue Importformate hinzugefügt werden. Die Zielobjekttypen sind immer gleich (Kunde, Adresse und mehr).

Ich habe über die Verwendung von Generika nachgedacht und etwas über das Fabrikmuster gelesen, aber ich bin ein ziemlich großer Neuling in diesem Bereich, daher ist jeder Rat mehr als willkommen.

Was ist ein geeignetes Entwurfsmuster, um dieses Problem zu lösen?

14
jao

Sie gehen mit ausgefallenen Konzepten über Bord, war zu früh. Generika - wenn Sie einen Fall sehen, verwenden Sie sie, aber ansonsten machen Sie sich keine Sorgen. Fabrikmuster - viel zu viel Flexibilität (und zusätzliche Verwirrung) dafür noch.

Halte es einfach. Verwenden Sie grundlegende Praktiken.

  1. Versuchen Sie sich die Gemeinsamkeiten zwischen einem Lesevorgang für XML und einem Lesevorgang für CSV vorzustellen. Dinge wie, nächste Aufnahme, nächste Zeile. Versuchen Sie sich eine Gemeinsamkeit vorzustellen, die das zu bestimmende Format mit den bekannten Formaten haben würde, da möglicherweise neue Formate hinzugefügt werden. Verwenden Sie diese Gemeinsamkeit und definieren Sie eine 'Schnittstelle' oder einen Vertrag, den alle Formate einhalten müssen. Obwohl sie sich an die Gemeinsamkeiten halten, können sie alle ihre spezifischen internen Regeln haben.

  2. Versuchen Sie zur Validierung der Daten, eine Möglichkeit zum einfachen Einfügen neuer oder anderer Validator-Codeblöcke bereitzustellen. Versuchen Sie also erneut, eine Schnittstelle zu definieren, an der jeder Validator, der für eine bestimmte Art der Datenkonstruktion verantwortlich ist, einen Vertrag einhält.

  3. Für die Erstellung der Datenkonstruktionen werden Sie wahrscheinlich mehr als alles andere von demjenigen eingeschränkt, der die vorgeschlagenen Ausgabeobjekte entwirft. Versuchen Sie herauszufinden, was der nächste Schritt für die Datenobjekte ist, und gibt es Optimierungen, die Sie vornehmen können, indem Sie die endgültige Verwendung kennen. Wenn Sie beispielsweise wissen, dass die Objekte in einer interaktiven Anwendung verwendet werden, können Sie dem Entwickler dieser App helfen, indem Sie "Zusammenfassungen" oder Zählungen der Objekte oder andere Arten von abgeleiteten Informationen bereitstellen.

Ich würde sagen, die meisten davon sind Vorlagenmuster oder Strategiemuster. Das gesamte Projekt wäre ein Adaptermuster.

11
Andyz Smith

Das Offensichtliche ist, Strategiemuster anzuwenden. Haben Sie eine generische Basisklasse ReadStrategy und für jedes Eingabeformat eine Unterklasse wie XmlReadStrategy, CSVReadStrategy usw. Auf diese Weise können Sie die Importverarbeitung unabhängig von der Verifizierungsverarbeitung und der ändern Ausgabeverarbeitung.

Abhängig von den Details kann es auch möglich sein, die meisten Teile des Import-Generikums beizubehalten und nur Teile der Eingabeverarbeitung auszutauschen (z. B. das Lesen eines Datensatzes). Dies kann zu Muster der Vorlagenmethode führen.

9
Doc Brown

Ein geeignetes Muster für ein Importdienstprogramm, das Sie möglicherweise in Zukunft erweitern müssen, ist die Verwendung von MEF. Sie können die Speichernutzung gering halten, indem Sie den benötigten Konverter im laufenden Betrieb aus einer Lazy-Liste laden und MEF-Importe erstellen, die mit Attributen versehen sind Dies hilft bei der Auswahl des richtigen Konverters für den Import, den Sie ausführen möchten, und bietet eine einfache Möglichkeit, die verschiedenen Importklassen voneinander zu trennen.

Jeder MEF-Teil kann so erstellt werden, dass er eine Importschnittstelle mit einigen Standardmethoden erfüllt, die eine Zeile der Importdatei in Ihre Ausgabedaten konvertieren oder eine Basisklasse mit der Grundfunktionalität überschreiben.

MEF ist ein Framework zum Erstellen einer Plug-In-Architektur. So werden Outlook und Visual Studio erstellt. All diese schönen Erweiterungen in VS sind MEF-Teile.

Um eine MEF-App (Managed Extensability Framework) zu erstellen, müssen Sie zunächst einen Verweis auf System.ComponentModel.Composition

Definieren Sie Schnittstellen, um festzulegen, was der Konverter tun soll

public interface IImportConverter
{
    int UserId { set; }        
    bool Validate(byte[] fileData, string fileName, ImportType importType);
    ImportResult ImportData(byte[] fileData, string fileName, ImportType importType);
}

Dies kann für alle Dateitypen verwendet werden, die Sie importieren möchten.

Fügen Sie einer neuen Klasse Attribute hinzu, die definieren, was die Klasse "exportieren" soll.

[Export(typeof(IImportConverter))]
[MyImport(ImportType.Address, ImportFileType.CSV, "4eca4a5f-74e0")]
public class ImportCSVFormat1 : ImportCSV, IImportConverter
{
 ...interface methods...
}

Dies würde eine Klasse definieren, die CSV-Dateien (eines bestimmten Formats: Format1) importiert und über benutzerdefinierte Attribute verfügt, mit denen MEF-Exportattribut-Metadaten festgelegt werden. Sie wiederholen dies für jedes Format oder jeden Dateityp, den Sie importieren möchten. Sie können benutzerdefinierte Attribute mit einer Klasse wie folgt festlegen:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class ImportAttribute : ExportAttribute
{
    public ImportAttribute(ImportType importType, ImportFileType fileType, string customerUID)
        : base(typeof(IImportConverter))
    {
        ImportType = importType;
        FileType = fileType;
        CustomerUID = customerUID;
    }

    public ImportType ImportType { get; set; }
    public ImportFileType FileType { get; set; }
    public string CustomerUID { get; set; }
}

Um die MEF-Konverter tatsächlich verwenden zu können, müssen Sie die MEF-Teile importieren, die Sie beim Ausführen Ihres Konvertierungscodes erstellen:

[ImportMany(AllowRecomposition = true)]
protected internal Lazy<IImportConverter, IImportMetadata>[] converters { get; set; }
AggregateCatalog catalog = new AggregateCatalog();

catalog sammelt die Teile aus einem Ordner, Standard ist der Speicherort der App.

converters ist eine verzögerte Liste der importierten MEF-Teile

Wenn Sie dann wissen, welche Art von Datei Sie konvertieren möchten (importFileType und importType), erhalten Sie einen Konverter aus der Liste der importierten Teile in converters

var tmpConverter = (from x in converters
                    where x.Metadata.FileType == importFileType
                    && x.Metadata.ImportType == importType 
                    && (x.Metadata.CustomerUID == import.ImportDataCustomer.CustomerUID)
                    select x).OrderByDescending(x => x.Metadata.CustomerUID).FirstOrDefault();

if (tmpConverter != null)
{
     var converter = (IImportConverter)tmpConverter.Value;
     result = converter.ImportData(import.ImportDataFile, import.ImportDataFileName, importType);
....
}

Der Aufruf an converter.ImportData verwendet den Code in der importierten Klasse.

Es scheint eine Menge Code zu sein, und es kann eine Weile dauern, bis Sie wissen, was los ist, aber es ist äußerst flexibel, wenn es darum geht, neue Konvertertypen hinzuzufügen, und es kann Ihnen sogar ermöglichen, zur Laufzeit neue hinzuzufügen.

7
Matt

Was ist ein geeignetes Entwurfsmuster, um dieses Problem zu lösen?

Bei C # -Idiomen wird dazu das integrierte Serialisierungsframework verwendet. Sie kommentieren die Objekte mit Metadaten und instanziieren dann verschiedene Serializer, die diese Annotationen verwenden, um Daten herauszureißen, um sie in die richtige Form zu bringen, oder umgekehrt.

XML-, JSON- und Binärformulare sind am häufigsten anzutreffen, aber ich wäre nicht überrascht, wenn andere bereits in einem Nice-Paket vorliegen, das Sie verwenden können.

0
Telastyn