将来拡張する必要があるかもしれないインポートユーティリティの適切なパターンは、MEFを使用することです。必要なコンバータを遅延リストからオンザフライでロードし、属性で装飾されたMEFインポートを作成することにより、メモリ使用量を低く抑えることができます実行しようとしているインポートに適したコンバータを選択するのに役立ち、インポートするさまざまなクラスを簡単に分離する方法を提供します。
各MEFパーツは、インポートファイルの行を出力データに変換したり、基本機能で基本クラスをオーバーライドしたりするいくつかの標準メソッドを使用して、インポートインターフェイスを満たすように構築できます。
MEFはプラグインアーキテクチャを作成するためのフレームワークです-その外観とVisual Studioの構築方法、VSのこれらの素敵な拡張機能はすべてMEFパーツです。
MEF(Managed Extensability Framework)アプリを構築するには、次への参照を含めることから始めます System.ComponentModel.Composition
コンバーターが何をするかを特定するインターフェースを定義する
public interface IImportConverter
{
int UserId { set; }
bool Validate(byte[] fileData, string fileName, ImportType importType);
ImportResult ImportData(byte[] fileData, string fileName, ImportType importType);
}
これは、インポートするすべてのファイルタイプに使用できます。
クラスが「エクスポート」するものを定義する属性を新しいクラスに追加します
[Export(typeof(IImportConverter))]
[MyImport(ImportType.Address, ImportFileType.CSV, "4eca4a5f-74e0")]
public class ImportCSVFormat1 : ImportCSV, IImportConverter
{
...interface methods...
}
これにより、CSVファイル(特定の形式:Format1)をインポートするクラスが定義され、MEFエクスポート属性メタデータを設定するカスタム属性が設定されます。インポートする形式またはファイルの種類ごとにこれを繰り返します。次のようなクラスでカスタム属性を設定できます。
[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; }
}
MEFコンバーターを実際に使用するには、変換コードの実行時に作成したMEFパーツをインポートする必要があります。
[ImportMany(AllowRecomposition = true)]
protected internal Lazy<IImportConverter, IImportMetadata>[] converters { get; set; }
AggregateCatalog catalog = new AggregateCatalog();
catalog
フォルダーからパーツを収集します。デフォルトはアプリの場所です。
converters
インポートされたMEFパーツの遅延リストです
次に、どの種類のファイルを変換するかがわかったら(importFileType
およびimportType
)、インポートされたパーツのリストからコンバータを取得します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);
....
}
への呼び出しconverter.ImportData
は、インポートされたクラスのコードを使用します。
たくさんのコードのように思えるかもしれませんが、何が起こっているのかを理解するには時間がかかりますが、新しいコンバータータイプの追加に関しては非常に柔軟であり、ランタイム中に新しいコンバータータイプを追加することもできます。