首页 > 代码库 > C# 关于PipeLine管道的用法

C# 关于PipeLine管道的用法

      pipeline类似于工厂加工,开始给一堆的零件,通过各个管道之后,从最后出口出来之后就是一件成品。管道链类似的责任。的主要区别是,链,每个“链接”传递到下一个,直到人知道如何处理它,那么这个过程停止。在管道,传递给每一个链的链接和潜在的修改通过。这就是“管道和过滤器”发挥作用,因为一个链接可以过滤管可能会增加其他链接。

       代码如下:

中间过程的接口:

 技术分享

一个上下文的结构:知道自己的上一个和下一个管道

 

 public class HandlerContext
    {
        private IEventHandler _handler;

        protected HandlerContext()
            : this(null)
        {
        }

        public HandlerContext(IEventHandler handler)
        {
            _handler = handler;
            Next =null;
            Prev = null;
        }

        public virtual IEventHandler Handler
        {
            get { return _handler; }
        }

        public static Task<object> Invoke(HandlerContext ctx, object data, TaskCompletionSource<Object> tcs = null)
        {
            var promise = tcs ?? new TaskCompletionSource<object>();
            if (ctx != null)
            {
                ctx.Handler.Process(ctx, data, promise);
            }
            return promise.Task;
        }

        public Task<object> FireProcess(object data)
        {
            var next = this.Next;
            return Invoke(next, data);
        }

        public Task<object> FireProcess(object data, TaskCompletionSource<Object> tcs)
        {
            var next = this.Next;
            return Invoke(next, data, tcs);
        }

        internal HandlerContext Next;
        internal HandlerContext Prev;
    }

 

PipeLine类:作用是添加中间的管道

 class AlarmPipeline
    {
        private readonly HandlerContext _head;
        private readonly HandlerContext _tail;

        public AlarmPipeline()
        {
            _head = new Decoder();
            _tail = new Renderer();
            _head.Next = _tail;
            _tail.Prev = _head;
        }

        public void AddLast(IEventHandler handler)
        {
            var newcontext = new HandlerContext(handler);
            var prev = _tail.Prev;
            prev.Next = newcontext;
            newcontext.Prev = prev;
            _tail.Prev = newcontext;
        }

        public void AddFirst(IEventHandler handler)
        {
            var newcontext = new HandlerContext(handler);
            var next = _head.Next;
            _head.Next = newcontext;
            newcontext.Next = next;
            newcontext.Prev = _head;
        }

        public bool AddAfter(IEventHandler prev, IEventHandler handler)
        {
            HandlerContext ctx = null;
            var cur = _head;
            while (cur != null)
            {
                if (cur.Handler == prev)
                {
                    ctx = cur;
                    break;
                }
                cur = cur.Next;
            }

            if (ctx == null)
                return false;

            var newcontext = new HandlerContext(handler);
            var next = ctx.Next;
            ctx.Next = newcontext;
            newcontext.Next = next;
            newcontext.Prev = ctx;
            next.Prev = newcontext;
            return true;
        }

        public void Remove(IEventHandler handler)
        {
            if (handler == null)
                return;

            var low = _head.Next;
            var high = _tail.Prev;
            do
            {
                if (low != null)
                {
                    if (low.Handler == handler)
                    {
                        _DoRemove(low);
                    }
                    low = low.Next;
                }

                if (high != null)
                {
                    if (high.Handler == handler)
                    {
                        _DoRemove(high);
                    }
                    high = high.Prev;
                }
            } while (low != high);
        }

        public void RemoveFirst()
        {
            if (_head.Next == null) return;
            this.Remove(_head.Next.Handler);
        }

        public void RemoveLast()
        {
            if (_tail.Prev == null) return;
            this.Remove(_tail.Prev.Handler);
        }

        private void _DoRemove(HandlerContext ctx)
        {
            var prev = ctx.Prev;
            var next = ctx.Next;
            prev.Next = next;
            next.Prev = prev;
        }

        public Task<object> Process(object data)
        {
            return HandlerContext.Invoke(_head, data);
        }

    }

 

比如第一个管道:

 class Decoder : HandlerContext, IEventHandler
    {
        public override IEventHandler Handler
        {
            get
            {
                return this;
            }
        }

        public void Process(HandlerContext context, object data, TaskCompletionSource<object> tcs)
        {
            string url = (string)data;
            
            var provider = new Provider(url);
            provider.Load();

            context.FireProcess(alarmdata, tcs);
        }
    }

C# 关于PipeLine管道的用法