.Net Core应用框架Util介绍(四)

 上篇介绍了Util Angular Demo的目录结构和运行机制,本文介绍Util封装Angular的基本手法及背后的动机。

  Angular应用由TsHtml两部分构成,本文介绍第一部分。

Angular Ts的封装

  Ts是Angular的代码部分,用于编写页面逻辑。

依赖注入( Dependency Injection )

  Ioc(Inversion of Control)已经成为.Net Core服务端编程的标配,Ioc解耦了类和依赖类之间的创建关系,让你开发出低耦合高内聚的系统。

  有了Ioc,你就可以面向抽象编程,注入依赖的接口,直接使用即可,而不用关心这个对象是如何创建出来的,也不用关心它具体是什么类型。

  Angular革命性的把Ioc引入到客户端脚本编程,从这里也可以看出,Angular实际上更适合具有服务端编程经验的开发人员。

  依赖注入是Ioc的一种使用模式,最常见的是构造方法依赖注入,将依赖对象定义在构造方法参数上,运行时,Ioc框架会把依赖对象“推送”进来,从使用的角度看,业务代码并不知道Ioc的存在,业务代码未与Ioc框架耦合,极易测试,代码也极度清爽,这一度让依赖注入成为Ioc的代名词,也是Ioc的推荐用法。

  当在Angular中使用依赖注入,有没有什么缺陷呢?下面来看个例子。

640?wx_fmt=png

 

  这段代码需要发送Http请求,所以从构造方法注入了Http。

  你必须要精确的知道Angular的哪个提供了Http服务,并且需要知道这个类在什么路径下。并不是每个类都像Http这么简短易记,这增加了大脑的负荷。

  对于专业Angular前端人员,这算不上什么缺陷,不过它确实增加了小团队使用Angular的学习成本。

  对于这个例子,哪怕你知道注入Http类,也清楚它的路径,但可能仍然引入了未知的Bug。Angular还提供了一个叫HttpClient的类,它在@angular/common/http路径下,HttpClient提供了拦截等高级机制,用来取代@angular/http包。如果你团队的一部分人使用HttpClient,并对Http进行了拦截,比如设置全局Token,另一部分人使用Http类发送请求,就会导致潜在的BUG。

  现在你清楚了对Angular API进行封装的必要性。

  封装是一种隐藏实现细节的手段,封装以后,你的注意力将从Angular Api转移到自己的业务上。

  对于Http请求,理想的API可能长成这样。 

640?wx_fmt=png

 

  首先,你并没有从@angular/common/http引入HttpClient,更没有在构造方法上注入它。这解决了需要记忆API的问题。

  其次,你并不清楚util.http封装的具体类型是什么,这统一了团队的API调用,也方便你在未来需要更换实现时不至于挨处查找。  

  我在前几年使用EasyUi时也封装了这样的Helper,通过直接引用并简单包装就完成了任务。 

  Helper往往表现为静态方法,面对Angular的Ioc体系,封装Helper变得很棘手,如何把需要的对象依赖注入到Helper静态方法中呢? 

  你如果直接import引入Angular API,这样封装出来的Helper行为上可能是错的,比如HttpClient的拦截机制,import创建的HttpClient实例脱离了Ioc框架,这将导致拦截失效。 

  一种办法是避开静态方法,你可以注入Util类,这样就可以拿到Angular Ioc容器中的相关实例了,这确实是个办法。 

  不过你如果希望使用静态方法,有没有办法现实呢? 

服务定位器( Service Locator )

  依赖注入威名远播,以至于很多人并不清楚它还有个同父异母的弟弟 —— 服务定位器。

  服务定位器是Ioc的另一种使用模式,你可以在代码中主动调用Ioc容器方法“拉取”依赖对象,这会导致你的代码与Ioc框架耦合,让代码也更难测试

  服务定位器俨然成为一种反模式,那么它是否已经一无是处了呢?

  我发现在大多数情况下,并不需要服务定位器,但在某些情况下,它却非常有用。

  哪种情况需要服务定位器?当你无法使用依赖注入时,就该它出手了。

  比如静态方法,你就无法使用依赖注入,通过服务定位器方式仍然可以访问Ioc,这对于封装框架Helper有非常重大的意义,我会在本系列后续文章介绍服务定位器在.Net Core服务端封装上的应用。 

  Util Angular Helper大量使用了服务定位器,以更简单的方式提供常用API。 

Util Angular Helper介绍

  • Helper

  它位于/Typings/util/common/helper.ts,包含一些常用操作,比如空值判断,类型转换等,helper.ts内部将操作委托给lodash等第三方js库。

640?wx_fmt=png640?wx_fmt=png

  • IocHelper

 

  它位于/Typings/util/angular/ioc-helper.ts

640?wx_fmt=png

  IocHelper内部保存了Angular Ioc容器实例,以方便其它Helper以服务定位器的方式来访问Ioc容器。

640?wx_fmt=png

  由于Angular Ioc具有分级特性,所以保存了模块级组件级两种容器,对于获取路由参数等操作,必须从组件容器获取实例,否则将导致错误的行为。

  在什么位置设置Angular Ioc容器呢?

  模块级容器在AppModule根模块中设置组件级容器需要在每个组件设置,这造成了不便,尚未找到更优雅的方式。

640?wx_fmt=png640?wx_fmt=png

 

  下面演示了IocHelper的用法。

let client = util.ioc.get<HttpClient>(HttpClient);
  • HttpHelper

  对于业务操作,使用得最频繁的Angular Api莫过于发送Http请求,从服务端获取Json数据,或将表单数据传递给服务端处理。

  Util通过HttpHelperWebApiForm三个Helper从不同层次对Http操作进行了封装

  HttpHelper位于/Typings/util/angular/http-helper.ts,对Angular HttpClient进行了简单包装,提供原始Http操作

640?wx_fmt=png

640?wx_fmt=png

  

  Util尽量提供同步Api,使用回调函数,而不是Rx的Observable或异步Promise,这样团队成员只要具备JQuery经验就能开发,降低了团队的学习成本。 

  在绝大多数情况下,你并不需要调用HttpHelper,WebApi和Form操作类会提供更多默认行为。

  • WebApi 

  在发送Http请求时,你通常需要处理异常 

  异常可分为Http异常业务异常两类。 

  Http异常是未成功的Http响应,比如Http状态码为500的服务器内部错误。Http异常通常和业务无关,所以每次发送请求设置Http异常处理是枯燥乏味的。 

  另一方面,Http返回200成功信号并不代表业务执行成功,所以不应该通过Http状态码来识别业务是否成功完成。 

  通过客户端和服务端约定标准通信格式可以简化异常处理。 

  先来看客户端结果类型

 

640?wx_fmt=png

 

  下面是服务端结果类型

 

640?wx_fmt=png

 

  WebApi操作类位于/Typings/util/common/webapi.ts,它在HttpHelper的基础上,设置了默认的Http异常处理,将Http异常输出到浏览器控制台,以方便排错,另外将服务端返回结果转换为客户端标准结果类型 

  下面展示了WebApi操作类的用法,handler方法是成功处理函数,你不用进行任何状态判断,WebApi内部已经处理过了。注意result参数并不是我们定义的标准Result类型,而是Result的data属性,也就是实际业务类型,前后端标准通信格式被封装起来。

640?wx_fmt=png

  • Form 

  对于管理后台,大多为表单操作,所以我们对表单需要特殊关照。 

  Form操作类位于/Typings/util/common/form.ts,它内置了一些表单常见操作。 

  当表单提交失败,通常会提示一个错误消息,以指示用户修正错误。

 640?wx_fmt=png

  错误提示是Form操作类的默认设置,你也可以取消它。

640?wx_fmt=png 

  有时候,你希望在提交表单前先确认一下。

 

640?wx_fmt=png

 

  通过设置一个属性就完成任务是不是很爽? 

 640?wx_fmt=png

  Form操作类还包含很多有用的功能,下面是它的参数定义

640?wx_fmt=gif Form操作类参数

  Form操作类建立在WebApi操作类之上,而WebApi操作类建立上HttpHelper之上,通过层层包装,让Http请求变得更加简单易用。

  • RouterHelper 

  Angular提供了路由机制,路由访问是仅次于Http请求的操作。

  通常需要从路由中获取参数

640?wx_fmt=png

640?wx_fmt=png

  RouterHelper用于操作路由,位于/Typings/util/angular/router-helper.ts,在内部使用服务定位器访问ActivatedRoute,简化了路由访问。

640?wx_fmt=png

  • Message 

  表单操作经常需要弹出各类消息框,比如成功提示框,错误提示框,确认提示框等。

  Message操作类集成封装了PrimeNg和Angular Material的消息框,它位于/Typings/util/common/message.ts

640?wx_fmt=png

 

  下面弹出了一个错误消息框

util.message.error("哈哈");

640?wx_fmt=png

  • Dialog

  Dialog操作类封装了Material弹出层,位于/Typings/util/common/dialog.ts

 640?wx_fmt=png

 640?wx_fmt=png

  下面演示了将外部网页加载到iframe中。

640?wx_fmt=png

 640?wx_fmt=png

  加载业务组件应使用dialogComponent属性。

640?wx_fmt=png

 

Util Angular CRUD基类介绍 

  Js是一种弱类型语言,通过原型链和闭包可以模拟出面向对象的特征,虽然看过一些文章说Js其实比C#这样的面向对象语言更加OO,不过我始终没有感觉出来,这或许是专业水平和我这种半吊子水平的区别所在吧。

  前几年我对Js的封装仅限于Helper或组件,服务端摸索出来的经验很难应用到Js,虽然能模拟出我想达到的效果,但却不是那么直观。

  虽然有人常说语言不是问题,语法更不是问题,但那指的是高手,在尚未达到高手境界以前,我们需要更优雅的语法糖,这使你写起来心情舒畅,开发业务效率倍增。

  Typescript提供了强大的语法糖,包括面向对象基本语法,泛型,lambda表达式等,Angular则提供了Ioc等服务端才具备的特性,这对于具备服务端架构设计经验的朋友,无疑是把利器。

  对于简单Crud操作,来回就那几句重复代码,能否在Angular开发中像C#一样封装个基类呢?

  有了Typescript和Angular,这是非常轻松的任务。

  • TableQueryComponentBase 

  对于简单Crud,通常在主界面放一个表格,并提供Crud操作。

  TableQueryComponentBase表格查询基类,它提供了从表格删除行,刷新表格,搜索等功能,位于/Typings/util/base/table-query-component-base.ts

  有了基类,业务组件将变得十分干净。

 640?wx_fmt=png

  Angular官方推荐将业务操作从组件分离,使用服务的形式依赖注入到组件,这让你的设计更加内聚。

  不过我没有机械的执行这一指南,仅在业务操作变得复杂时使用这种方式,在更多的简单场景,我会把数据操作直接内置到组件中。

  • EditComponentBase

  EditComponentBaseCrud编辑基类,除了提交表单以外,它还能从路由取得Id并从服务端加载数据,位于/Typings/util/base/edit-component-base.ts

 

 640?wx_fmt=png

  ApplicationEditComponent示例类重写了loadById和submit方法,删除掉同样可以工作,当你有特殊要求的时候进行重写。

  • FormComponentBase 

  一个常见的需求,当表单已经被更改时,跳转页面需要提示用户保存。

  FormComponentBase是表单基类,位于/Typings/util/base/form-component-base.ts,它提供了表单变更值检查方法。

 640?wx_fmt=png

  • TreeTableQueryComponentBase 与 TreeEditComponentBase

  与TableQueryComponentBase和EditComponentBase类似,这两兄弟也是用来支持简单Crud操作的,不过它们用来支持树型关系。

  继承基类,收工,不要在简单Crud上浪费过多时间。

 640?wx_fmt=png

 640?wx_fmt=png

  Util Demo的role示例演示了树型Crud的用法。

小结

  本文简单介绍了Util Angular Helper的封装,使用服务定位器封装成链式,所有helper都内聚在util这个命名空间下,这大幅提升了Angular的易用性,对于常用功能,不用记忆任何API,凭借一点模糊的印象就能够完成任务。

  另外介绍了为简化Crud提供的基类,这和服务端Crud封装很相似,得益于Typescript和Angular所提供的强大语法糖。

  未完待续,Angular 组件封装及TagHelper将在下篇介绍。

  写文需要动力,请大家多多支持,点下推荐,Github点下星星

  Util应用框架交流一群: 24791014

  Util应用框架地址:https://github.com/dotnetcore/util

相关文章:

  • .Net Core应用框架Util介绍(一)

  • .Net Core应用框架Util介绍(二)

  • .Net Core应用框架Util介绍(三)

原文地址: https://www.cnblogs.com/xiadao521/p/Util-Introduction-4.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319674.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2020牛客暑期多校训练营(第四场)

2020牛客暑期多校训练营&#xff08;第四场&#xff09; 这场属实有点难受 文章目录A Ancient DistanceB Basic Gcd Problem题目代码&#xff1a;C Count New StringD Dividing StringsE EliminateF Finding the Order题意&#xff1a;题解&#xff1a;代码&#xff1a;G Geome…

《C# 程序员的自我修养》送书活动结果公布

截止到9月28日24&#xff1a;00 &#xff0c;本次送书活动《C# 程序员的自我修养》共收到150多位同学参与回复。以下5位同学将获赠书籍一本&#xff1a;夏树、Damon、水墨清华、天天、kang以上同学请加小二微信领取赠书小二微信&#xff1a;geffzhang.NET社区新闻&#xff0c;深…

使用 dotTrace 分析 .NET Core 代码问题

0.背景在项目开发之中&#xff0c;前期可能主要以保证任务完成为主&#xff0c;对于性能优化主要在于开发完成之后再来进行。可能在测试的时候发现部分接口的代码执行时间过长&#xff0c;但是又毫无头绪&#xff0c;这个时候你就需要性能分析工具来协助你排查问题了。常规性能…

【每日一题】7月17日题目精讲—BOWL 碗的叠放

【每日一题】7月17日题目精讲—BOWL 碗的叠放 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 小H有n个碗需要放进橱柜&#xff0c;她希望将他们叠起来放置。你知道每个碗都…

基于Ocelot的gRpcHttp网关

什么是gRpcHttp网关通俗的讲就是将gRpc提供的服务以rest api的形式提供出去&#xff0c;不需要再单独的写一个webapi去做这件事。gRpcHttp网关好处减少不必要代码&#xff0c;减少中间层提高通讯效率。以前可能是这样用了gRpc网关后是这样gRpcHttp网关提供哪些功能可以直接加载…

CF917D-Stranger Trees【矩阵树定理,高斯消元】

正题 题目链接:https://www.luogu.com.cn/problem/CF917D 题目大意 给出nnn个点的一棵树&#xff0c;对于每个kkk求有多少个nnn个点的树满足与给出的树恰好有kkk条边重合。 解题思路 矩阵树有一个统计所有树边权和的和用法&#xff0c;就是把变量变成一个形如wx1wx1wx1的多项…

COSCon'18 面向全宇宙招募志愿者啦!

2018 中国开源年会&#xff08;COSCon18-China Open Source Conference 2018) 志愿者招募工作今日正式启动&#xff01;我们诚挚地欢迎开源社区的朋友们及高校的同学们加入志愿工作者团队&#xff0c;与国内外众多开源项目基金会、公司、大神等齐聚一堂&#xff0c;共襄盛举。招…

讲重点,看趋势——Microsoft Ignite 2018的回顾和展望

一年一度的微软技术大会——Microsoft Ignite 2018上周在奥兰多召开&#xff0c;目前已经落下帷幕。我没有去现场&#xff0c;但据说这次的盛况空前&#xff0c;创下微软之最。确实&#xff0c;这些年来&#xff0c;微软内部非常重视 Iginte&#xff0c;上至最高管理层&#xf…

算法工程师的危机

本文为沙漠之鹰第68篇原创文章9月20号讯飞AI同传语音造假的新闻刷爆科技圈&#xff0c;科大讯飞股价应声下跌3.89%&#xff08;不是65.3%&#xff0c;标题党文章害死人&#xff09;。 吃瓜群众纷纷感慨&#xff0c;有多少人工&#xff0c;就有多少智能。小编偷换概念玩的溜AI概…

Cover the Tree(2020多校第二场C)

Cover the Tree 文章目录题意&#xff1a;题解&#xff1a;代码题意&#xff1a; 一个无向树&#xff0c;选择最少数量的链子&#xff0c;能将树上所有边覆盖&#xff0c;答案不唯一 (1≤n≤2105&#xff09; 链子就是两点之间的边 看看样例 输入 5 1 2 1 3 2 4 2 5输出 2 2…

[模板]多项式全家桶小记(求逆,开根,ln,exp)

前言 这里的全家桶目前只包括了ln,exp,sqrtln,exp,sqrtln,exp,sqrt。还有一些类似于带余数模&#xff0c;快速幂之类用的比较少的有时间再更&#xff0c;NTTNTTNTT这种前置知识这里不多说。 还有一些基本的导数和微积分内容要了解&#xff0c;建议不懂的可以先去翻翻高二数学…

牛客网【每日一题】7月21日题目精讲—区间权值

来源&#xff1a;牛客网&#xff1a; 区间权值 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 1048576K&#xff0c;其他语言2097152K 64bit IO Format: %lld题目描述 输入描述: 第一行一个正整数 n 第二行 n 个正整数 a1…an 第三行 n 个正…

C# 函数式编程:LINQ

一直以来&#xff0c;我以为 LINQ 是专门用来对不同数据源进行查询的工具&#xff0c;直到我看了这篇十多年前的文章&#xff0c;才发现 LINQ 的功能远不止 Query。这篇文章的内容比较高级&#xff0c;主要写了用 C# 3.0 推出的 LINQ 语法实现了一套“解析器组合子&#xff08;…

2020牛客暑期多校训练营(第六场)

2020牛客暑期多校训练营&#xff08;第六场&#xff09; 额&#xff0c;睡了一下午&#xff0c;直接错过了比赛。。。 文章目录A African Sort题意&#xff1a;题解&#xff1a;代码&#xff1a;B Binary VectorC Combination of Physics and Maths题意&#xff1a;题解&#x…

P4001-[ICPC-Beijing 2006]狼抓兔子【对偶图】

正题 题目链接:https://www.luogu.com.cn/problem/P4001 题目大意 给出一个类似于 的网格图&#xff0c;求起点到终点的最小割。 解题思路 最小割直接跑网络流&#xff0c;然后发现dinicdinicdinic都过不了。&#xff08;好像加点玄学优化就能过&#xff09; 然后上点科技…

私有云方案——利用阿里云云解析实现DDNS

各位都是程序员&#xff0c;工作中是不是遇到个类似情况。在家里研究的一些开源代码或写的一些demo或试验代码&#xff0c;在工作中正好需要参考一下&#xff0c;但是在家里的电脑上。虽然这些都可以用云盘/网盘之类的来完成&#xff0c;源代码也可以托管到源码平台。但是这些都…

2020年首届算法竞赛网络挑战赛直播讲解课程

比赛链接 菜鸡的我&#xff0c;第四名。。 A 矛盾激化 题意 给定地图&#xff0c;这个地图有两个出口&#xff0c;现在我们需要求出从所有点到任意一个出口的距离中的最短路径的最大值 本题为输出答案题&#xff0c;给定你一种情况&#xff0c;然后输出它的答案 题解 如果…

光荣与梦想 | XMove动作捕捉系统(一)

今年春节回到老家&#xff0c;翻出了2011年春节时焊电路用过的松香和和硬盘角落里的代码。感慨万分&#xff0c;遂有此文。文章过长&#xff0c;分为两部分&#xff0c;本文为2010-2011年&#xff0c;XMove从第一代到第三代的故事。诞生于考研的第一代保研尚未确定&#xff0c;…

大型科技公司架构:中台模式的爱与恨

大型企业面对快速变化的市场形势&#xff0c;需要有像创业公司一样快速的反应能力。然而由于复杂的人员和层级关系&#xff0c;大企业做到“拥抱变化”是很困难的。传统以职能部门分治的树状组织架构&#xff0c;若一个底层员工有个好点子&#xff0c;就不得不自下而上说服管理…

牛客网 【每日一题】7月27日题目精讲—乌龟棋

来源&#xff1a;牛客网&#xff1a; 乌龟棋 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 131072K&#xff0c;其他语言262144K 64bit IO Format: %lld文章目录乌龟棋题目描述题解&#xff1a;代码&#xff1a;题目描述 小明过生日的时候&…