zoukankan      html  css  js  c++  java
  • Middleware

    Middleware的艺术

    定义

    Middleware直译叫中间件,目前在百度上很难找到一个简单明了的含义解释,.Net下以前也比较难以看到它的身影,但在Microsoft.Owin里,多个地方都看到MiddleWare,我近来在尝试理解Middleware,并在实际中模仿应用,本文章将我的个人理解和大家分享一下。

    Middleware的抽象

    Microsoft.Owin的Middleware

    复制代码
    public abstract class OwinMiddleware
    {
        protected OwinMiddleware(OwinMiddleware next);
    
        protected OwinMiddleware Next { get; set; }
    
        public abstract Task Invoke(IOwinContext context);
    }
    复制代码

    微软把Middleware定义在抽象类,除了Invoke的中间件执行入口,还有一个Next的中间件属性,两者都是非常抽象。Invoke正是本中间件的处理逻辑,参数IOwinContext包含问题试卷和答题卡,Next表示下一个中间件,如果本中间件不想解决此问题,那么就让Next来解决这个问题,以此类推。提问题的人不用关注是谁回答了问题,他只关注答案了够了。

    简单的Middleware接口

    如果我们把中间件定义为接口,那么一个简单的中间件接口可以如下:

    public interface IMiddleware
    {
        IMiddleware Next { set; }
        Answer GetAnswer(Question question);
    }

    当然,在一些实际项目中,中间件的抽象程度不一样,所以中间件的执行方法是根据实际需要作合理的设计,但Next一般不会有变化,它都是代表下一个中间件。

    Middleware和插件的区别

    插件是应用程序的功能扩展,它可以只关注自身的功能的实现,它可能不是带问题的,但各插件的执行接口是一样的,最简单的插件接口可以如下:

    public interface IPlug
    {
        // 加载执行插件
        void Init();
    }

    Middleware是问题解决单元抽象,它往往是由多个单元同时协同工作,各单元虽然没有直接关系,但Next属性还是得到了下个中间件的实例,提供给本中间件来传递。Middlware随着数量的增多,解决的问题各类也可以越多,和插件越多功能越丰富有相似。

    Middleware的使用场景

    我曾经写过《.Net下一个类型转换神器》,近期在代码重构,发现这玩意很适合使用中间件来实现。在类型转换中,调用者想要的是这种:

    复制代码
    /// <summary>
    /// 将value转换为目标类型
    /// </summary>
    /// <param name="value">要转换的值</param>
    /// <param name="targetType">转换的目标类型</param>
    /// <returns></returns>
    object Convert(object value, Type targetType);
    复制代码

    value和targetType千变万化,一口可吃不完,本着单一职责原则,我们应该要写很多转换单元,每个单元只负责一种类型转换,转换器由N多个转换单元组成,如果转换单元是中间件,抽象的中间件接口应该如下:

    复制代码
        /// <summary>
        /// 定义类型转换单元的接口
        /// </summary>
        public interface IConvertMiddleware
        {
            /// <summary>
            /// 设置下一个转换单元
            /// </summary>
            IConvertMiddleware Next { set; }
    
            /// <summary>
            /// 将value转换为目标类型
            /// </summary>
            /// <param name="上下文">context</param>
            /// <returns></returns>
            object Convert(ConvertContext context);
        }
    复制代码

    实际当中,我们可能未必需要这么抽象,我的实际接口是

    复制代码
        /// <summary>
        /// 定义类型转换单元的接口
        /// </summary>
        public interface IConvert
        {
            /// <summary>
            /// 设置转换器
            /// </summary>
            Converter Converter { set; }
    
            /// <summary>
            /// 设置下一个转换单元
            /// </summary>
            IConvert NextConvert { set; }
    
            /// <summary>
            /// 将value转换为目标类型
            /// </summary>
            /// <param name="value">要转换的值</param>
            /// <param name="targetType">转换的目标类型</param>
            /// <returns></returns>
            object Convert(object value, Type targetType);
        }
    复制代码

    然后,我们来一个一个地来实现转换单元:

    某个单元的实现如下:

     

    /// <summary>
    /// 表示不作转换的转换单元
    /// </summary>
    public class NoConvert : IConvert
    {
    /// <summary>
    /// 转换器实例
    /// </summary>
    public Converter Converter { get; set; }

    /// <summary>
    /// 下一个转换单元
    /// </summary>
    public IConvert NextConvert { get; set; }

    /// <summary>
    /// 将value转换为目标类型
    /// </summary>
    /// <param name="value">要转换的值</param>
    /// <param name="targetType">转换的目标类型</param>
    /// <returns></returns>
    public object Convert(object value, Type targetType)
    {
    if (targetType == typeof(object))
    {
    return value;
    }

    if (value != null && targetType == value.GetType())
    {
    return value;
    }

    return this.NextConvert.Convert(value, targetType);
    }
    }

    NoConvert

    更广泛的Middleware

    我近来在开发开源项目《NetworkSocket》,自从看到Microsoft.Owin之后的中间件之后,觉得Middleware可以在很多领域中使用,现在这个项目里的协议解析实现者都已经完全由中间件来开发,功能越来丰富,但复杂度感觉没有增大。看看下面代码,你应该能感觉到Middleware的甜味。

    var listener = new TcpListener();
    listener.Use<HttpMiddleware>();
    listener.Use<JsonWebSocketMiddleware>();
    listener.Use<FastMiddleware>();            
    listener.Start(1212);
  • 相关阅读:
    拓扑排序学习
    快速排序+归并排序
    邻接表的两种实现(链表和数组模拟)
    一起学Windows Phone7开发(十四.一 Phone Task)
    一起学Windows Phone7开发(十四.四 Web Task)
    一起学Windows Phone7开发(十四.三 Multimedia Task)
    一起学Windows Phone7开发(十五. Device)
    一起学Windows Phone7开发(十四.五 Market Task)
    深入学习Windows Phone7(三. Visual State Manager)
    深入学习Windows Phone7(一. Reactive Extension)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5103925.html
Copyright © 2011-2022 走看看