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

标签 c# generics interface

我正在尝试实现过滤器/管道模式,以便我可以获取输入,通过多个过滤器对其进行处理并在最后获得输出。

当输入类型和最终输出类型相同并且每个过滤器也使用相同类型时,我可以很容易地做到这一点。但是,我想输入一种类型并输出另一种类型。

例如 通过文件名获取 csv 文件,将其加载到单独的字符串中,解析它们,验证并输出为 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行

Error 2 Argument 1: cannot convert from 'BusinessLogic.FilterCsvFileLoader<BusinessObjects.FilenameObject,BusinessObjects.CSVFile>' to 'BusinessLogic.IFilter<BusinessObjects.IBusinessObject,BusinessObjects.IBusinessObject>'
C:\Users\davidc\Documents\Visual Studio 2010\Projects\MPMeFeed\TestConsole\Program.cs 15 23 TestConsole

最佳答案

这里的问题是 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;
    }
}

关于c# - 每个过滤器的输入/输出类型不同的通用管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8308155/

相关文章:

c# - 字符串的实际长度

c# - 如何访问 Windows 中的特殊目录?

swift - 泛型和协议(protocol)类型的功能参数在实践中有什么区别?

swift - Swift 如何消除表达式上下文中类型参数的歧义?

c# - 如果这个类没有 Dispose 方法,它如何实现 IDisposable?

java - 尝试用Java模拟其他类中的线程行为

c# - 切换到 IIS8 后断开连接时 ASP.NET 处理请求

c# - 如果模型实现了 INotifyPropertyChanged,ViewModel 应该如何注册/注销 PropertyChanged 事件?

c# - 帮助解决 C# 泛型错误 - "The type ' T' 必须是不可为空的值类型”

java - 连接两个 Java 应用程序的适当方法