2011-11-29 42 views
5

我正在嘗試實現篩選器/管道模式,以便我可以接受輸入,通過多個篩選器處理它並在最後得到輸出。其中輸入/輸出類型對於每個篩選器不同的通用管道

當輸入類型和最終輸出類型相同並且每個篩選器也使用相同類型時,我可以輕鬆完成此操作。但是,我想輸入一個類型並獲得另一個類型。

例如 通過文件名獲取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 

我的目的是要能夠有IFilter<T,U>一個List,T and U are IBusinessObject

不過,我得到一個「嘗試將IFilter<IBusinessObject, IBusinessObject>添加到列表時,無法從BusinessObjectImplementation轉換爲IBusinessObject「。

Apols所有的代碼...它的最後一部分將不會編譯


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>()); 
     } 
    } 

唯一的例外是在.Register線之上

錯誤2參數1:不能從 'BusinessLogic.FilterCsvFileLoader<BusinessObjects.FilenameObject,BusinessObjects.CSVFile>' 轉換爲 'BusinessLogic.IFilter<BusinessObjects.IBusinessObject,BusinessObjects.IBusinessObject>'
C:\用戶\ davidc \文檔\ Visual Studio 2010 \ Projects \ MPMeFeed \ TestConsole \ Program.cs 15 23 TestConsole

回答

5

你有這裏的問題是,FilterCsvFileLoader<FilenameObject, CSVFile>工具IFilter<FilenameObject, CSVFile>這不是IFilter<IBusinessObject, IBusinessObject>即使FilenameObject & CSVFile派生類型從IBusinessObject的。

這是一個常見的錯誤。

嘗試這樣代替:

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/

類是在裝配ObservablePipelineShuttle.Core.infrastructure

它可能會給你一些想法。