2017-02-23 16 views
2

制御の反転を正しく使用しようとしています。私のアプリは正常に動作しています。私はUnityをIoCコンテナとして使用しています。しかし、どの具体的なクラスを使うかという選択肢があるときは間違っていると思います。制御と選択の反転

この例では、特定のデータソースからデータを取得するクラスがあります。ファイルタイプによって、データアクセサークラスが呼び出されます。

このサービスクラスは、型をチェックし、切り替えを行い、次にどの具体的なクラスを使用するかを選択します。

しかし、ここではIoCの原則を壊しているようです。クラス内の何かを「新しくする」ことです。私はこのサービスクラスにはもはや注入しません。なぜなら、現時点では、私がどのファイルタイプで作業しているのかを決定していないからです。だから、私は「注入」をコメントしなければならず、かなりハードコードしなければならなかった。

ここにコードを抽出します。

public class DataService : IDataService 
    { 
     IFileReader _fileReader; 
     public DataService(IFileReader fileReader) 
     { 
      // _fileReader = fileReader; 
     } 

     /// <summary> 
     /// Returns reporting data based on a group of export files. 
     /// </summary> 
     /// <param name="files">A list of files to analyse</param> 
     /// <returns></returns> 
     private List<RawFileData> GetRawData(string[] files) 
     { 
      foreach (var file in files) 
      { 
       // validate files exists. 
       switch (GetFileType(Path.GetFileName(file))) 
       { 
        case "CSV": 
         { 
          fileIsOK = true; 
          _fileReader = new CSVileConnector(); 
          break; 
         } 
        case "TXT": 
         { 
          fileIsOK = true; 
          _fileReader = new TXTFileConnector(); 
          break; 
         } 
        default: 
         break; 
       } 
       if (fileIsOK) 
       { 
        var finedata = _fileReader.ReadData(file); 
        data.Add(new RawFileData 
        { 
         DataItems = finedata, 
         FileName = file 
        }); 
       } 
      } 

      return data; 
     } 

これは、このような状況を処理する正しい方法ですか?クラス作成時に、どの子クラスが「依存する」のか分かりません。そしてそれを論理で決定し、正しいConcreteクラスを新しくしますか?

+0

おそらく、iocはルールではないだけのことです。 –

+0

ええ、これは真実かもしれない - それゆえ私がなぜそれを原則と呼んだのか。しかし、できる限り原則に固執するのは良いことです。私はやっていることが正しいかどうかを確認しています - それを行うより良い方法があります。サービス層がデータ型を決定しないようにすることができます。これはデータレイヤーで行う必要があります。ちょっとしたケースでは、私の「スイッチ」がレイヤーを下に移動し、IoCがここに戻ります。しかし、私はデータ層で同じ問題を抱えています。私はその下の正しい具体的なクラスを新しくする必要があります。 – Craig

答えて

1

読者の選択を読書自体から分離することが1つ改善される可能性があります。これはIFileReader _getDataReader(string filename)というプライベートメソッドです。だからあなたのforeachループでvar reader = _getDataReader(filename);と言う。読者があなたのクラスの私有財産である理由は、構築されておらず、継続的に変化し、その使用範囲がGetRawDataに制限されているためです。何ですか?コンストラクタを介して注入することは、インターフェイス定義にGetDataReader(string)のクラスです。それ自体は秘密のDictionary<string, Type>を保持することができ、それはファイルの拡張子をキーとして持ち、そのファイルの読者を値として持ちます。 yauが必要な場合は、app.configで設定することもできます。それはService Locatorパターンとして知られています。

さまざまな理由でthis is actually an anti-patternという良い引数があります。 2つの選択肢しかなく、この方法で読むのは簡単だから、あなたはそれを考えていると主張するかもしれませんが、読者の選択を読書そのものから切り離すことは、少なくとも簡単な場所にあなたを置きます必要に応じて変更してください。

+1

チャドに感謝します。私は_getDataReaderビットの分離が好きです。それはずっと簡単なコードです。私は、「考え過ぎた」ビットとサービスロケータについて同意します。私たちのチームの1つの要件は、それを過度にエンジニアリングすることではなく、読みやすく維持しやすい慣用コードを作成することです。クラスのコンストラクタには注入がないことは問題ありません。注入はファイルタイプに遅れます。したがって、Inversion of Control全体はまだ有効です - そうですか? – Craig

関連する問題