2011-11-29 15 views
5

入力を受け取り、多数のフィルタで処理し、最後に出力を得るために、フィルタ/パイプラインパターンを実装しようとしています。入力/出力タイプがフィルタごとに異なる汎用パイプライン

入力タイプと最終出力タイプが同じで、各フィルタも同じタイプを使用している場合は、これを簡単に実行できます。しかし、私は1つのタイプを入力し、別のタイプを取得したい。

ファイル名でcsvfileを取得し、個々の文字列に読み込んで解析し、検証してxmlとして出力します。擬似コードの例:

input = filename 
filter = load csv file <filename, list<string>> 
filter = parse csv <list<string>, list<businessobject>> 
filter = validate objects <list<businessobject>, list<businessobject>> *... return type same as input type in this case.* 
filter = create xml <list<businessobject>, XDocument> 
filter = validate XDoc <XDocument, XDocument> 
output = XDocument 

ここでは、私がこれまで持っているものです。

IFilter, FilterBase, FilterImplementation 
IPipeline, Pipeline 
IBusinessObject, BusinessObject, BusinessObjectImplementation 

私の意図は、しかし、私は「Aを取得T and U are IBusinessObject

IFilter<T,U>のリストを持ってできるようにしましたIFilter<IBusinessObject, IBusinessObject>をリストに追加しようとすると、BusinessObjectImplementationからIBusinessObjectに変換できません。


public interface IFilter<T, U> 
     where T : IBusinessObject 
     where U : IBusinessObject 
    { 
     U Execute(T input); 
    } 

    public abstract class FilterBase<T, U> : IFilter<T, U> 
     where T : IBusinessObject 
     where U : IBusinessObject, new() 
    { 
     protected abstract U Process(T input); 

     public U Execute(T input) 
     { 
      return Process(input); 
     } 

    } 

    public class FilterCsvFileLoader<T, U> : FilterBase<T, U>, IFilter<T, U> 
     where T : FilenameObject, IBusinessObject 
     where U : CSVFile, IBusinessObject, new() 
    { 
     public FilterCsvFileLoader() 
     { } 

     protected override U Process(T input) 
     { 
      U result = new CSVFile(input) as U; 
      return result; 
     } 
    } 

public interface IPipeline 
    { 
     IBusinessObject Execute(IBusinessObject input); 

     IPipeline Register(IFilter<IBusinessObject, IBusinessObject> filter); 
    } 

    public class Pipeline : IPipeline 
    { 
     private List<IFilter<IBusinessObject, IBusinessObject>> _filters = new List<IFilter<IBusinessObject, IBusinessObject>>(); 

     public IBusinessObject Execute(IBusinessObject input) 
     { 
      var result = input; 
      foreach (var filter in _filters) 
      { 
       result = filter.Execute(result); 
      } 
      return result; 
     } 

     public IPipeline Register(IFilter<IBusinessObject, IBusinessObject> filter) 
     { 
      _filters.Add(filter); 
      return this; 
     } 
    } 

public interface IBusinessObject 
    { 
     bool Validate(); 
     List<string> ValidationErrors { get; } 
    } 

    public class BusinessObject : IBusinessObject 
    { 
     private List<BusinessRule> _businessRules = new List<BusinessRule>(); 

     private List<string> _validationErrors = new List<string>(); 

     public List<string> ValidationErrors 
     { 
      get { return _validationErrors; } 
     } 
     protected void AddRule(BusinessRule rule) 
     { 
      _businessRules.Add(rule); 
     } 

     public bool Validate() 
     { 
      bool isValid = true; 

      _validationErrors.Clear(); 

      foreach (BusinessRule rule in _businessRules) 
      { 
       if (!rule.Validate(this)) 
       { 
        isValid = false; 
        _validationErrors.Add(rule.ErrorMessage); 
       } 
      } 
      return isValid; 
     } 
    } 

    public class FilenameObject : BusinessObject, IBusinessObject 
    { 
     string _filename; 

     public string Filename 
     { 
      get { return _filename; } 
     } 

     public FilenameObject(string filename) 
     { 
      _filename = filename; 
     } 
    } 

    public class CSVFile : BusinessObject, IBusinessObject 
    { 
     private string _filename; 
     private string[] _splitChar = new string[] { "," }; 

     public List<List<string>> Lines { get; set; } 

     public CSVFile() 
     { } 

     public CSVFile(FilenameObject filename) 
      : this() 
     { 
      _filename = filename.Filename; 
      Lines = new List<List<string>>(); 
     } 

     private void ImportFile() 
     { 
      FileInfo fi = new FileInfo(_filename); 
      using (StreamReader sr = new StreamReader(fi.Open(FileMode.Open, FileAccess.Read, FileShare.None))) 
      { 
       String readline; 
       while ((readline = sr.ReadLine()) != null) 
       { 
        var line = (from l in readline.Split(_splitChar, StringSplitOptions.None) 
           select l.Trim()).ToList(); 
        Lines.Add(line); 
       } 
      } 
     } 
    } 

class Program 
    { 
     static void Main(string[] args) 
     { 
      var pipeline = new Pipeline() 
      .Register(new FilterCsvFileLoader<FilenameObject, CSVFile>()); 
     } 
    } 
をコンパイルしません...その非常に最後の部分のすべてのコードの

Apols 0

例外が

エラー2引数1以上.Registerラインである: 'BusinessLogic.FilterCsvFileLoader<BusinessObjects.FilenameObject,BusinessObjects.CSVFile>' から変換することはできません
'BusinessLogic.IFilter<BusinessObjects.IBusinessObject,BusinessObjects.IBusinessObject>' へ C:ビジュアル\ davidc \ドキュメント\ \ユーザープロジェクト\ MPMeFeed \ TestConsole \ Program.csを\ Studio 2010の 15 23 TestConsole

答えて

5

あなたはここにある問題はFilterCsvFileLoader<FilenameObject, CSVFile>FilenameObject & CSVFileIBusinessObjectから派生しているにもかかわらずIFilter<IBusinessObject, IBusinessObject>の派生型ではありませんIFilter<FilenameObject, CSVFile>を実装していることです。

これはよくある間違いです。

ではなく、このような何かを試してみてください:

public interface IFilter 
{ 
    IBusinessObject Execute(IBusinessObject input); 
} 

public interface IFilter<T, U> : IFilter 
    where T : IBusinessObject 
    where U : IBusinessObject 
{ 
    U Execute(T input); 
} 

public abstract class FilterBase<T, U> : IFilter<T, U> 
    where T : IBusinessObject 
    where U : IBusinessObject, new() 
{ 
    protected abstract U Process(T input); 

    IBusinessObject IFilter.Execute(IBusinessObject input) 
    { 
     return this.Execute((T)input); 
    } 

    public U Execute(T input) 
    { 
     return Process(input); 
    } 
} 

public interface IPipeline 
{ 
    IBusinessObject Execute(IBusinessObject input); 

    IPipeline Register<T, U>(IFilter<T, U> filter) 
     where T : IBusinessObject 
     where U : IBusinessObject; 
} 

public class Pipeline : IPipeline 
{ 
    private List<IFilter> _filters = new List<IFilter>(); 

    public IBusinessObject Execute(IBusinessObject input) 
    { 
     var result = input; 
     foreach (var filter in _filters) 
     { 
      result = filter.Execute(result); 
     } 
     return result; 
    } 

    public IPipeline Register<T, U>(IFilter<T, U> filter) 
     where T : IBusinessObject 
     where U : IBusinessObject 
    { 
     _filters.Add(filter); 
     return this; 
    } 
} 
+0

ありがとうございました、これは動作しませんでした理由として良い説明。 – BlueChippy

0

私は多くが不明または予測不可能な状況に遭遇したときにことを見つけますタイプは私達の友人が関与しているobjectが出場する。それはあなたのために働くかもしれません。

は、それはいくつかのあなたの部分に掘りがかかる場合がありますが、私のサービス・バスで使用されるコアインフラストラクチャ・アセンブリにおける一般的なパイプラインの実装があります:

http://shuttle.codeplex.com/

クラスは、アセンブリ内のObservablePipelineあるShuttle.Core.infrastructure

それはあなたにいくつかのアイデアを与えるかもしれない。

関連する問題