2

以下は、別のクラスに注入される依存関係の実装です。

public class CsvDataProvider : ICsvDataProvider
{
    readonly ICsvReaderFactory _factory;

    public CsvDataProvider(ICsvReaderFactory factory)
    {
        _factory = factory;
    }

    public IEnumerable<TRecord> GetData<TRecord>(string filepath) where TRecord : class
    {
        var reader = _factory.CreateCsvReader(filepath);

        return reader.GetRecords<TRecord>();
    }
}

readerによって作成されたは、CSVファイルのfactoryすべての行を読み取り、各行をのインスタンスに変換しますTRecordreader私はコードを所有しておらず、GetRecords<TRecord>()メソッドを変更できません。

これは私が立ち往生しているところです:

public class CsvDataMigrationController
{
    readonly ICsvDataProvider _provider;
    readonly ICsvDataMigration _migration;

    public CsvDataMigrationController(ICsvDataProvider provider, ICsvDataMigration migration)
    {
        _provider = provider;
        _migration = migration;
    }

    public void ProcessFile(string path)
    {
        var records = _provider.GetData<I_DONT_WANT_TO_EXPLICITLY_SAY>(path); //<-- Help!

        _migration.Migrate(records);
    }
}

目的は、データプロバイダーと移行手順クラスをに注入することですCsvDataMigrationController。コントローラはデータプロバイダーを呼び出してデータを取得し、データを移行クラスに渡します。

  • CsvDataMigrationController関係するデータの種類について知りたくありません。
  • CsvDataProvider移行について知りたくありません。
  • CsvDataMigrationデータがどこから来たのか知りたくありません。

これを達成する方法について何かアドバイスはありますか?

注:CsvDataMigration説明に役立たないと思ったため、クラスを含めませんでしたが、必要に応じて含めます。

4

2 に答える 2

3

変更することはできないのでGetRecords、おそらく最も簡単な方法は、移行インターフェイスにレコードタイプを要求し、リフレクションを使用してGetData、実行時に取得したタイプでジェネリックメソッドを呼び出すことです。何かのようなもの:

public void ProcessFile(string path)
{
    Type recordType = _migration.InputRecordType;

    var getDataMethod =
        _provider.GetType()
        .GetMethod("GetData")
        .MakeGenericMethod(recordType);

    var records = getDataMethod.Invoke(_provider, new object[] { path });
    _migration.Migrate(records);
}
于 2013-02-19T05:59:05.500 に答える
3

通常、次のような一般的でない代替案を定義します。

public interface ICsvDataProvider
{
    IEnumerable GetData(string filepath, Type recordType) 

    IEnumerable<TRecord> GetData<TRecord>(string filepath) 
        where TRecord : class;
}

だからあなたはこれを次のように呼ぶことができます

public class CsvDataMigrationController
{
    private string targetTypeName = ...;

    public void ProcessFile(string path)
    {
        var recordType = Type.GetType(this.targetTypeName);
        var records = _provider.GetData(path, recordType);
        _migration.Migrate(records);
    }
}

このように、ジェネリックメソッドは非ジェネリックメソッドのほんの少しの構文糖衣です。

(@Cameronの回答のように)リフレクションを使用することも別の解決策です。どちらの場合も、(ジェネリックメソッドが必要とするコンパイル時ではなく)実行時にターゲットタイプを知っている必要があります。

于 2013-02-19T06:00:12.500 に答える