LayIM.NetClient 組件開發記錄

來源:互聯網
上載者:User

標籤:blank   path   list   .net   9.png   閱讀   nali   init   分層   

前言

  好久沒寫部落格了。前階段看了下Hangfire組件,後來對其代碼比較感興趣,當時不太瞭解他如何產生的頁面和一些訪問請求等。後來看了下原始碼,發現原來是 OWIN 在搞怪。於是乎開始深入研究Hangfire原始碼,當然只是Route和Razor部分,具體他的核心業務後台執行任務我沒研究。因為,我想到了之前做的LayIM的一個對接。那時候寫的代碼和項目耦合度太高,於是冒出一個寫LayIM Owin外掛程式的想法。直接開工吧。

開工

  主要參考了Hangfire的Dashboard部分。 https://github.com/HangfireIO/Hangfire/tree/master/src/Hangfire.Core/Dashboard

  與之前的代碼相比,這些代碼都沒有放入WebUI 端中,而且,分層也比較少。就一個 Owin中介軟體和SqlServer的實現。代碼結構如下:(我自己當然寫不出啦,參考上文連結中的代碼)

  

  用過OWIN的都知道,就是通過IAppBuilder介面註冊中介軟體。其實還是挺複雜的,雖然照著寫了出來。為了避免誤導觀眾,我就不多解釋了。不過路由那一塊我我可以說一下我的理解。

  首先定義路由集合,集合中包含所有註冊的路徑和實現 ILayIMDispatcher 介面的 Dispatcher。

  

  public class RouteCollection    {        private readonly List<Tuple<string, ILayimDispatcher>> _dispatchers = new List<Tuple<string, ILayimDispatcher>>();        /// <summary>        /// 註冊路由        /// </summary>        /// <param name="pathTemplate">路由地址</param>        /// <param name="dispatcher">處理方法</param>        public void Add(string pathTemplate, ILayimDispatcher dispatcher)        {            Error.ThrowIfNull(pathTemplate, nameof(pathTemplate));            Error.ThrowIfNull(dispatcher, nameof(dispatcher));            _dispatchers.Add(new Tuple<string, ILayimDispatcher>(pathTemplate, dispatcher));        }        /// <summary>        /// 根據Path尋找對應的Dispatcher        /// 通過Regex來找到匹配的結果        /// </summary>        /// <param name="path">路徑</param>        /// <returns></returns>        public Tuple<ILayimDispatcher, Match> FindDispatcher(string path)        {            if (path.Length == 0) path = "/";            foreach (var dispatcher in _dispatchers)            {                var pattern = dispatcher.Item1;                if (!pattern.StartsWith("^", StringComparison.OrdinalIgnoreCase)) {                    pattern = $"^{pattern}";                }                if (!pattern.EndsWith("$", StringComparison.OrdinalIgnoreCase)) {                    pattern += "$";                }                var match = Regex.Match(path, pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Singleline);                if (match.Success) {                    return new Tuple<ILayimDispatcher, Match>(dispatcher.Item2, match);                }            }            return null;        }    }

  請求,進入中介軟體的處理代碼:

                var owinContext = new OwinContext(env);                var context = new OwinLayimContext(storage,options, env);                var path =  owinContext.Request.Path.Value;                //匹配路由                var findResult = routes.FindDispatcher(path);                //如果沒有匹配到,執行下一個                if (findResult == null) {                    return next(env);                }                //匹配成功之後執行 Dispatch                context.UriMatch = findResult.Item2;                //執行具體disptach方法,返回相應結果                return findResult.Item1.Dispatch(context);

  舉例來說:Layim中的初始化介面。定義為 /init  需要參數為 id. 那麼在路由中,註冊如下:

       //AddQuery只是又封裝了一層,內部還是調用了Add方法。       Routes.AddQuery<long>("/init", "id", (context, uid) =>             {                  //返回處理結果             });

  在上邊的例子中,AddQuery方法,註冊了一個 SingleParameterQueryDispatcher<T> 的處理類。 他的作用就是處理擁有單個參數的類型為T的請求。具體代碼如下:

        public async Task Dispatch(LayimContext context)        {            var request = context.Request;            var response = context.Response;            var parameterValue = request.GetQuery(_parameterName);            //如果不是Get請求,返回方法不允許            if (!CommandMethod.Equals(request.Method, StringComparison.OrdinalIgnoreCase))            {                response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;                await Task.FromResult(false);            }            //返回結果為"application/json";            context.Response.ContentType = "application/json";            //將參數轉化為相應的類型,有 null 異常            T value = (T)Convert.ChangeType(parameterValue, typeof(T));            //執行具體處理函數            var result = _command(context, value);            //序列化結果            var json = context.Options.Serializer.SerializeObject(result);            //返回            await context.Response.WriteAsync(json);        }
總結

  簡單了介紹一下路由部分的內容,相信很多小夥伴也是看的雲裡霧裡的。看懂OWIN機制,就能夠懂了。我也是大部分借鑒(抄襲)了Hangfire中的代碼。

  基本思路:

  1. 註冊路由
  2. 實現路由匹配方法
  3. 找到對應的處理器
  4. 處理方法,返回結果

  在不懂的話,建議直接閱讀原始碼,閱讀原始碼能有意想不到的收穫。

附:LayIM.NetClient中介軟體的使用方法。其中IM通訊我使用了融雲,所以在其中也做了一些封裝。

  

 public class Startup    {        public void Configuration(IAppBuilder app)        {            //使用SQL Server            GlobalConfiguration.Configuration.UseSqlServer("LayIM_Connection");            //使用layim api 6tnym1brnmpt7            app.UseLayimApi("/layim", new LayimOptions            {                RongCloudSetting = new RongCloudSetting()            });        }    }

  LayIM中註冊的路由如下:

  

  運行結果:

  

  

  擷取融雲token的方法:

  

  

  代碼運行正常

   

 

   最後:我覺得Owin中介軟體真的很方便。首先能夠避免web項目中寫太多的重複的商務邏輯。(當然,layim部分抽出成api也可以)  通過封裝成 LayIM.NetClient中介軟體以後,不管是webform還是mvc都可以通過Owin來適配。後邊還會繼續完善。今天就到此為止吧~~

LayIM.NetClient 組件開發記錄

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.