Patrón de diseño para la importación de datos de varios tipos de origen y varios tipos de destino

14

Tengo que diseñar y construir un script de importación (en C #) que pueda manejar lo siguiente:

  • leer datos de varias fuentes (XML, XSLX, CSV)
  • verificar datos
  • escriba los datos en varios tipos de objetos (cliente, dirección)

Los datos provendrán de varias fuentes, pero una fuente siempre tendrá un formato de importación (ya sea csv, xml, xslx). Los formatos de importación pueden variar de una fuente a otra. Se pueden agregar nuevos formatos de importación en el futuro. Los tipos de objetos de destino son siempre los mismos (cliente, direcciones y algunos más).

He estado pensando en usar genéricos y leí algo sobre el patrón de fábrica, pero soy un noob bastante grande en esta área, así que cualquier consejo es más que bienvenido.

¿Cuál es un patrón de diseño apropiado para resolver este problema?

    
pregunta jao 22.08.2013 - 18:27

4 respuestas

11

Te estás excediendo con los conceptos de fantasía era demasiado pronto. Genéricos: cuando vea un caso, utilícelos, pero de lo contrario no se preocupe. Patrón de fábrica: demasiada flexibilidad (y mayor confusión) para esto todavía.

Mantenlo simple. Utiliza prácticas fundamentales.

  1. Intente imaginar las cosas comunes entre hacer una lectura para XML, una lectura para CSV, lo que sea. Cosas como, próximo disco, siguiente línea. Dado que se pueden agregar nuevos formatos, intente imaginar los elementos comunes que el formato a determinar tendría con los conocidos. Use estos elementos comunes y defina una 'interfaz' o un contrato que todos los formatos deben cumplir. Aunque se adhieren a los puntos en común, todos pueden tener sus reglas internas específicas.

  2. Para validar los datos, intente proporcionar una manera de insertar fácilmente nuevos bloques de códigos de validación o diferentes. Entonces, nuevamente, intente definir una interfaz donde cada validador, responsable de un tipo particular de construcción de datos, se adhiera a un contrato.

  3. Para crear las construcciones de datos, es probable que se vea limitado por quienquiera que diseñe los objetos de salida sugeridos más que nada. Intente averiguar cuál es el siguiente paso para los objetos de datos, y hay algunas optimizaciones que pueda hacer al saber el uso final. Por ejemplo, si sabe que los objetos se utilizarán en una aplicación interactiva, podría ayudar al desarrollador de esa aplicación al proporcionar "sumas" o conteos de los objetos u otros tipos de información derivada.

Yo diría que la mayoría de estos son patrones de plantillas o patrones de estrategia. Todo el proyecto sería un patrón de adaptador.

    
respondido por el Andyz Smith 23.08.2013 - 04:06
8

Lo obvio es aplicar patrón de estrategia . Tenga una clase base genérica ReadStrategy y para cada formato de entrada una subclase como XmlReadStrategy , CSVReadStrategy , etc. Esto le permitirá cambiar el procesamiento de importación independientemente del procesamiento de verificación y el procesamiento de salida.

Según los detalles, también es posible mantener la mayoría de las partes de la importación genérica e intercambiar solo partes del procesamiento de entrada (por ejemplo, la lectura de un registro). Esto puede llevarlo a patrón de método de plantilla .

    
respondido por el Doc Brown 22.08.2013 - 19:10
7

Un patrón adecuado para una utilidad de importación que tal vez necesite extender en el futuro sería usar MEF: puede mantener el uso de memoria bajo cargando el convertidor que necesita sobre la marcha de una lista lenta, cree importaciones de MEF que sean decorado con atributos que ayudan a seleccionar el convertidor correcto para la importación que está intentando realizar y proporciona una manera fácil de separar las diferentes clases de importación.

Cada parte del MEF puede construirse para satisfacer una interfaz de importación con algunos métodos estándar que convierten una fila del archivo de importación en sus datos de salida o anulan una clase base con la funcionalidad básica.

MEF es un marco para crear una arquitectura de plug-in: es cómo se construyen Outlook y Visual Studio, todas esas hermosas extensiones en VS son partes de MEF.

Para crear una aplicación MEF (Managed Extensability Framework), comience por incluir una referencia a System.ComponentModel.Composition

Defina interfaces para especificar qué hará el convertidor

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

Esto se puede utilizar para todos los tipos de archivos que desea importar.

Agregue atributos a una nueva clase que defina lo que la clase "Exportará"

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

Esto definiría una clase que importará archivos CSV (de un formato particular: Formato1) y tiene atributos personalizados que establecen los Metadatos de atributos de exportación de MEF. Repetirías esto para cada formato o tipo de archivo que quieras importar. Puede establecer atributos personalizados con una clase como:

[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; }
}

Para utilizar realmente los convertidores de MEF, necesita importar las partes de MEF que crea cuando se ejecuta el código de conversión:

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

catalog recolecta las partes de una carpeta, la ubicación predeterminada de la aplicación es

converters es una lista lenta de las partes importadas del MEF

Luego, cuando sepa qué tipo de archivo desea convertir ( importFileType y importType ) obtenga un convertidor de la lista de piezas importadas en 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);
....
}

La llamada a converter.ImportData usará el código en la clase importada.

Puede parecer una gran cantidad de código y puede llevarle un poco de tiempo lo que está pasando, pero es extremadamente flexible cuando se trata de agregar nuevos tipos de convertidores e incluso puede permitirle agregar nuevos durante el tiempo de ejecución.

    
respondido por el Matt 22.08.2013 - 20:17
0
  

¿Cuál es un patrón de diseño apropiado para resolver este problema?

Los lenguajes

C # implican el uso del marco de serialización incorporado para hacer esto. Anota los objetos con metadatos y, a continuación, crea una instancia de diferentes serializadores que usan esas anotaciones para extraer los datos y colocarlos en la forma correcta, o viceversa.

Los formularios Xml, JSON y binarios son los más comunes, pero no me sorprendería si ya existieran otros en un formato empaquetado agradable para que los consumas.

    
respondido por el Telastyn 22.08.2013 - 19:17

Lea otras preguntas en las etiquetas