Um padrão adequado para um utilitário de importação que talvez você precise estender no futuro seria usar o MEF - você pode manter o uso de memória baixo carregando o conversor necessário em tempo real a partir de uma lista lenta, criar importações de MEF decoradas com atributos que ajudam a selecionar o conversor certo para a importação que você está tentando executar e fornece uma maneira fácil de separar as diferentes classes de importação.
Cada parte do MEF pode ser construída para satisfazer uma interface de importação com alguns métodos padrão que convertem uma linha do arquivo de importação em seus dados de saída ou substituem uma classe base pela funcionalidade básica.
O MEF é uma estrutura para criar uma arquitetura de plug-in - é como o Outlook e o Visual Studio são criados, todas essas extensões adoráveis no VS são partes do MEF.
Para criar um aplicativo MEF (Managed Extensability Framework), comece incluindo uma referência a System.ComponentModel.Composition
Definir interfaces para especificar o que o conversor fará
public interface IImportConverter
{
int UserId { set; }
bool Validate(byte[] fileData, string fileName, ImportType importType);
ImportResult ImportData(byte[] fileData, string fileName, ImportType importType);
}
Isso pode ser usado para todos os tipos de arquivos que você deseja importar.
Adicione atributos a uma nova classe que defina o que a classe "Exportará"
[Export(typeof(IImportConverter))]
[MyImport(ImportType.Address, ImportFileType.CSV, "4eca4a5f-74e0")]
public class ImportCSVFormat1 : ImportCSV, IImportConverter
{
...interface methods...
}
Isso definiria uma classe que importará arquivos CSV (de um formato específico: Format1) e possui atributos personalizados que configuram os metadados do atributo de exportação MEF. Você repetiria isso para cada formato ou tipo de arquivo que deseja importar. Você pode definir atributos personalizados com uma classe 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 realmente usar os conversores MEF, você precisa importar as partes que você cria quando o código de conversão é executado:
[ImportMany(AllowRecomposition = true)]
protected internal Lazy<IImportConverter, IImportMetadata>[] converters { get; set; }
AggregateCatalog catalog = new AggregateCatalog();
catalog
coleta as partes de uma pasta, o padrão é o local do aplicativo.
converters
é uma lista lenta das peças importadas do MEF
Então, quando você souber que tipo de arquivo deseja converter ( importFileType
e importType
), obtenha um conversor na lista de peças importadas emconverters
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);
....
}
A chamada para converter.ImportData
usará o código na classe importada.
Pode parecer muito código e pode demorar um pouco para você entender o que está acontecendo, mas é extremamente flexível quando se trata de adicionar novos tipos de conversor e pode até permitir que você adicione novos durante o tempo de execução.