通用管道,每个过滤器的输入/输出类型不同

时间:2011-11-29 09:04:59

标签: c# generics interface

我正在尝试实现一个过滤器/管道模式,以便我可以接收输入,通过多个过滤器处理它并在最后获得输出。

当输入类型和最终输出类型相同且每个过滤器也使用相同类型时,我可以轻松完成此操作。但是,我想输入一种类型并获得另一种类型。

e.g。 按文件名获取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> T and U are IBusinessObject

的列表

但是,在尝试向列表中添加BusinessObjectImplementation时,我收到“无法从IBusinessObject转换为IFilter<IBusinessObject, 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:\ Users \ davidc \ Documents \ Visual Studio 2010 \ Projects \ MPMeFeed \ TestConsole \ Program.cs   15 23 TestConsole

2 个答案:

答案 0 :(得分:6)

您遇到的问题是FilterCsvFileLoader<FilenameObject, CSVFile>实现了IFilter<FilenameObject, CSVFile>,即使IFilter<IBusinessObject, IBusinessObject>&amp; 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; } }

这是一个常见的错误。

尝试这样的事情:

{{1}}

答案 1 :(得分:0)

我发现每当遇到涉及许多未知或不可预测类型的情况时,我们的朋友object就会发挥作用。这可能对你有用。

您可能需要进行一些挖掘,但我的服务总线使用的核心基础架构组件中有一个通用的管道实现:

http://shuttle.codeplex.com/

汇编ObservablePipeline

中的班级为Shuttle.Core.infrastructure

它可能会给你一些想法。