Un modello adatto per un'utilità di importazione che potrebbe essere necessario estendere in futuro potrebbe essere l'utilizzo di MEF: è possibile mantenere basso l'utilizzo della memoria caricando il convertitore necessario al volo da un elenco pigro, creare importazioni MEF decorate con attributi che aiutano a selezionare il convertitore giusto per l'importazione che si sta tentando di eseguire e fornisce un modo semplice per separare le diverse classi di importazione.
Ogni parte MEF può essere costruita per soddisfare un'interfaccia di importazione con alcuni metodi standard che convertono una riga del file di importazione nei dati di output o sovrascrivono una classe base con la funzionalità di base.
MEF è un framework per la creazione di un'architettura plug-in: è il modo in cui sono costruiti Outlook e Visual Studio, tutte quelle belle estensioni in VS sono parti MEF.
Per creare un'app MEF (Managed Extensability Framework) iniziare con l'inclusione di un riferimento a System.ComponentModel.Composition
Definire le interfacce per specificare cosa farà il convertitore
public interface IImportConverter
{
int UserId { set; }
bool Validate(byte[] fileData, string fileName, ImportType importType);
ImportResult ImportData(byte[] fileData, string fileName, ImportType importType);
}
Questo può essere utilizzato per tutti i tipi di file che si desidera importare.
Aggiungi attributi a una nuova classe che definisca ciò che la classe "Esporterà"
[Export(typeof(IImportConverter))]
[MyImport(ImportType.Address, ImportFileType.CSV, "4eca4a5f-74e0")]
public class ImportCSVFormat1 : ImportCSV, IImportConverter
{
...interface methods...
}
Ciò definirebbe una classe che importerà i file CSV (di un particolare formato: Format1) e ha attributi personalizzati che impostano i metadati degli attributi di esportazione MEF. Lo ripeteresti per ogni formato o tipo di file che desideri importare. Puoi impostare attributi personalizzati con una classe come:
[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; }
}
Per utilizzare effettivamente i convertitori MEF è necessario importare le parti MEF create durante l'esecuzione del codice di conversione:
[ImportMany(AllowRecomposition = true)]
protected internal Lazy<IImportConverter, IImportMetadata>[] converters { get; set; }
AggregateCatalog catalog = new AggregateCatalog();
catalog
raccoglie le parti da una cartella, l'impostazione predefinita è la posizione dell'app.
converters
è un elenco pigro delle parti MEF importate
Quindi, quando si conosce il tipo di file che si desidera convertire ( importFileType
e importType
) ottenere un convertitore dall'elenco delle parti importateconverters
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 chiamata a converter.ImportData
utilizzerà il codice nella classe importata.
Potrebbe sembrare un sacco di codice e può volerci un po 'per capovolgere quello che sta succedendo, ma è estremamente flessibile quando si tratta di aggiungere nuovi tipi di convertitore e può anche permetterti di aggiungerne di nuovi durante il runtime.