Asp.net 面向接口可扩展框架之核心容器

新框架的容器部分终于调通了!容器实在太重要了,所以有用了一个名词叫“核心容器”。

容器为什么那么重要呢?这个有必要好好说道说道。

1、首先我们从框架名称面向接口编程说起,什么是面向接口编程?(这个度娘回答一下)

      解读一下:类是个体的定义(建模), 个体的每一方面都可以是一个接口

      说白点,其一接口可以代表对象(类)一个方面,再说透点对象可能是多面手(继承多个接口),能在不同场景(作为不同接口的实例)下正常工作

      其二每个接口可以有不同实现,只要实现了这个接口,基本上就可以替换这个位置来正常工作

2、我觉得面向接口编程本质上还是面向对象编程,可是更抽象,更便于扩展和替换

     我们需要很多很多的对象来支持系统的功能需要和扩展需求,还需要每个位置上的对象方便“随时”替换,扩充

     那我们怎么来管理这个庞大的对象库呢,如何方便的编排以便管理?这里就要说到容器了,容器可以很好的胜任这个工作。

3、容器的作用

  我认为容器就是仓库,就是柜子,就是盒子,以便我们可以按自己喜欢的方式存放自己的对象,以便需要的时候能方便的找到他们

      好的容器还能维护对象的创建、生命周期、控制反转(IOC)、依赖注入(DI)、拦截方法执行(AOP)等


前面废话太多,老规矩先上例子

一、对象的创建和管理由容器负责

1、以下还是前面那篇上下文的例子,使用容器来简化后的代码

 以上代码是不是简单漂亮多了

 2、代码虽然简单了,功能一点都没有水分哦,看看以下执行结果截图

是不是结果上一篇的完全一样啊。

3、结果一样不算什么,改个配置(不改代码),看看结果

4、再改配置(还是不该代码)

这次生动了吧,一家人各有各的个性了,是不是很炫啊。

5、大家看看配置

明眼人一眼就能看出这个是Unity容器的配置;有人说,你不是不要依赖Unity容器吗?我发誓确实没有依赖Unity容器,但我也没说不用Unity啊。我只是要做一个框架,其他技术方案都可以集成进来,容器也是。

你熟悉Unity就用Unity,你熟悉Spring.net也可以放心使用,只要你封装一下并继承这个框架的容器接口,再注册进来就可以正常工作了

 

二、使用了Unity容器,但不依赖Unity容器

1、调用容器的地方没有依赖Unity

这个测试项目除了系统的几个引用,就只引用了这个主框架了

2、主框架没有引用Unity容器

没骗你们吧?真没依赖Unity,主框架甚至除了几个简单的系统引用,没有依赖(引用)任何第三方组件,但是这一点都不影响我使用大量第三方的库,因为这里是"面向接口可扩展框架"

是不是现在又对接口有了进一步的理解了,是不是“面向接口可扩展框架”这个名字有点名符其实味道了。

 

三、下面来解密他到底怎么运行的

1、看入口,看应用程序(这里是控制台程序)的引用

哈哈,是不是找到了,终于看到Unity引用了

但是不要被表象所迷惑,其实这里的主角是Fang.Unity,因为这个项目可以不直接引用Unity容器,Fang.Unity是对Unity容器的封装。

控制台程序对Unity相关dll是运行时依赖,并不是编译依赖,这里直接引用上是为了便于调试

2、继续探究原理

Fang.Unity总不会是自动运行的吧?当然不是,上代码

上图有一句不起眼,但是非常重要的一行代码“Fang.Unity.ContainerFactory.Init()”,他就是“罪魁祸首”了

换句话话说,Unity容器是完全作为插件在本框架中运行的,如果我不调用Unity的Init,调用Spring.net的Init,那当前所有地方调用的就都是Spring.net容器了。

有人说这也太不方便了吧,当然不是每次使用容器都要调用,如果是web项目可以在global的Application_Start中调用一下就Ok了,也可以在HttpModule的Init中调用也可以。

大部分时候我们在开发中大量使用容器,但并不用想我具体用什么容器。

换句话说,我熟悉Unity容器,我使用Unity容器配置调试通过的组件给你使用,但是你一直都用Spring.net(或者其他容器),你调用Spring.net容器的封装,把配置修改为Spring.net的配置,代码一样能正常运行

注:前提是组件开发的时候使用的是框架的容器支持,没有直接引用Unity容器和直接调用Unity容器的代码

3、还是看一眼Fang.Unity.ContainerFactory.Init是什么鬼吧(哈哈,要不睡不着了)

Unity容器就不在这里展开,我会单开一篇讲Unity容器和Unity封装等

 

四、核心容器解析

1、容器相关实现类截图

2、核心类图如下:

稍作解析各个类的分工:

     A:IContainer接口是定义容器需要的基本功能

     B:IContainerFactory定义容器工厂接口

     C:GlobalContainer是个静态配置类,提供注册外部容器组件功能及提供调用容器的Api

这个是实现容器插件化的关键,这个实现是参考了Asp.net Mvc的DependencyResolver

   D:SimpleContainer提供一个简单和默认的容器和容器工厂实现

  AppContext中的上线文容器就是他实现的,如果不配置扩展容器功能,使用的容器就是他了,但是他其实就是一个字典缓存,存个东西,取个东西,完全没有问题,复杂配置及DI等就没戏了

   E:ContainerWrapper是个容器封装拦截类,拦截容器的操作,以便增加特性和功能

       这个以后再展开讲,里面有一个很有意思的特性

   F:ContainerFactoryCacheWrapper是容器工厂封装及缓存

       也就是外面实现的容器工厂是不用考虑单例模式缓存什么的,他给包办了,而且把每个生产好的容器对象检查和打包好

 

五、多容器的应用

1、我们需要多个容器来编排众多对象

就好比我从超市一次性买回来很多东西,有鸡蛋、排骨、蔬菜、儿童玩具、衣服等等。我不能弄一个大箱子全部放进去,也不乱放,不能把衣服和排骨一起放冰箱(会被媳妇骂死的)。排骨进冰箱冷冻室,鸡蛋和蔬菜进冰箱冷藏室。儿童玩具放儿童床。衣服放衣柜。

代码做了微调,再看运行结果

 有人说,你怎么越改越复杂啊,代码复杂一点点,但是配置更加有条理有的时候是值得的,看配置

这只是一个简单拆分容器的方案,也可以按对象图谱来划分容器,这样更加合理,因为对象之间有相互的依赖关系,使用容器来做控制反转也就是这个意思

如果是支持子容器的容器工具(Unity就支持),一个系统就可以按树状划分容器,整个系统的公共配置是根容器,每个子系统都有各自的容器配置,每个子系统的各个模块也有自己的容器配置,子容器可以继承父容器也可以覆盖父容器的配置

2、下面做一个树状子容器的例子

这个效果是不是杠杠的,代码也是漂亮的一塌糊涂,是怎么配置的,也看一下吧

总结一下,容器名是优美的链式语法,配置文件是树状管理结构,Perfect!!!

 

六、容器扩展

1、SimpleContainer容器不"Simple"

前面有介绍IContainer接口,细心看一下就会发现有添加(Regist)和读取(Resolve)方法,但是没有删除对象的方法,我们要删除怎么办

但是SimpleContainer可是有Remove方法,使用框架的容器功能就要放弃自己更加强大的容器功能是不是有点遗憾,可不可以鱼和熊掌兼得?当然可以,上下文那个就是用SimpleContainer实现的,作用域结束就从容器中删除对象。

我们这里再举一个简单的例子演示一下

使用完整的框架容器支持还是可以使用自定义容器的更多功能技巧就是IContainer接口有一个Provider属性用来对外暴露原容器对象的Provider属性,只要把自己想扩展暴露的扩展功能放在Provider属性中即可

当然也可以和SimpleContainer的Provider直接返回容器本身

细心的用户可能注意到这个例子里面出现一个新的东西(Fang.Framework.Factory.Create),这个和前面的GlobalContainer.Factory.Create效果是一样的,Fang.Framework.Factory是个静态类,负责把框架的主要工厂方法都汇总起来,以便查找和使用。

但是还是要特别强调一下,这种扩展方式虽然简单,但是并不推荐使用

因为你一旦对Provider强制类型转化的时候你就依赖特定的容器实现了,这样这些的代码就可能不能适应其他容器,也就是说你的代码强依赖特定的容器,这样就违背了本框架的精神。

一句话,你需要更多的特性就会牺牲一些通用性,如果每段代码都是特例,不能扩展,那这个系统就该有麻烦了。

 

2、使用ContainerWrapper的扩展

2.1 前面有提到ContainerWrapper时用来包装容器的,通过框架产生的容器(IContainer)对象都是被ContainerWrapper包装过的,而且ContainerWrapper拦截IContainer所有的方法

只要定义一个容器包装类继承ContainerWrapper,重写自己想要扩展的功能,定义一个ContainerFactory类(继承IContainerFactory)返回的包装后的容器对象,框架里面有调用一个CheckWrapper方法处理新产生的容器对象,如果对象可以转化为ContainerWrapper对象就不需要再次包装了

2.2 还有一个扩展技巧就是先按没有扩展的方式注册容器工厂

然后对容器工厂再次扩展返回ContainerWrapper对象,也就是自己定义容器封装功能代替框架默认的封装逻辑

以后可能会开发一个通用DI标注扩展功能,就打算使用这种方式,获取对象的时候检查当前对象或者类型是否有对应标注(Attribute),如果有就调用特殊逻辑处理,没有统一的DI标注,使用DI就不得不依赖特定容器,这样就会影响代码复用性和可迁移性。

 

七、容器"黑科技"

1、快速检索

用黑科技来改造树状结构的例子

可以配置很多容器来管理对象,但调用我们却不用直接和每个容器打交道,只要按一定规则命名,可以使用任一个容器对象来调取任一个对象配置

如果以上黑科技再配合上DI,那就更Perfect了!!!

注:这里面有一个插曲,一个工程师使用容器配置DI,他指着一个配置文件里面的一个节点对我说,我想要把这个节点DI到我的Controller上。我对他解释,"DI不能这样的,你必须把这个节点放在根容器中,或者定义一个分区并指向一个容器,然后把这个节点复制到那个新容器中"。这个工程师听得满头雾水,迷茫的说"我只是想把这个节点映射到我的Controller上,...";有了这个黑科技,我可以放心告诉他,你写一个DI标注就可以了

 

就写这么多了,还有很多东西要写,也有很多功能待开发,以后再补充吧。

提供测试源代码下载。

特别强调,本框架还在开发中,并没有进行完全测试,不排除有重大bug的可能性,切忌暂时不要拿到自己现实项目中,出现问题后果自负,而且本框架还没有正式开源,没有开源授权。

原文地址:http://www.cnblogs.com/xiangji/p/5423613.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

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

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

相关文章

pre2-flink单机部署与job提交

【README】 本文记录了flink单机部署,以及flink job2种提交方式; 【1】flink 单机部署 step1)下载flink 包; Apache Flink: Stateful Computations over Data Streamshttps://flink.apache.org/ step2)解压 tar -z…

到底什么是跨域?附解决方案

转载自 到底什么是跨域?附解决方案什么是跨域 要了解跨域,先要说说同源策略。 同源策略是由 Netscape 公司提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都会使用这个策略。 所谓同源是指,域名,协议&#xf…

vue 字典_【开源】基于Vue的前端组件库HeyUI

说道vue组件库,目前主流的基本就是iview和element。今天又发现一个很不错的。HeyUI。组件也很丰富,入门比较简单。反正开源框架我们有不嫌多,多多益善啊。感兴趣的可以看看。关于HeyUIHeyUI 是一套基于 Vue2.0 的开源 UI 组件库,主…

(译)java8-流定义

【README】 本文翻译自 Stream In Java - GeeksforGeeks , 主要介绍了java8流; 【1】流 1)流定义:流是支持各种方法的对象序列(一系列对象),这些方法可以流水线化调用以产生期望结果&#xff…

基于CefSharp构建基于Chromium的应用程序

chromium是google chrome浏览器所采用的内核,最开始由苹果的webkit发展而出,由于webkit在发展上存在分歧,而google希望在开发上有更大的自由 度,2013年google决定自己开发webcore的分支,叫做Blink引擎,而后…

最新后端架构师技术图谱

转载自 最新后端架构师技术图谱深呼吸,慢慢学,技术长路漫漫… 数据结构二叉树完全二叉树平衡二叉树二叉查找树(BST)红黑树B-,B,B*树LSM 树队列集合链表、数组字典、关联数组栈树BitSet常用算法KPM 算法选择…

ansible脚本-Playbook(一)

Playbook组成部分: task 任务:包含目标主机上执行的操作,使用模块定义这些操作,每个任务都是一个模块的调用Variables变量:存储和传递数据,变量可以自定义,可以在playbook当中定义为全局变量&a…

三级pc技术_第十九周PC、笔电、数码周边新品汇总:AMD英特尔激战正酣

【dogkeji-科技犬】各位网友周末好,又到了2020年第十九周的PC、笔电、数码周边新品发布汇总时刻(2020年5月4日至2020年5月9日),那么本周有那些PC、笔电、数码周边新品发布呢?通过科技犬的汇总我们来一起回顾一下吧。AM…

【DDD/CQRS/微服务架构案例】在Ubuntu 14.04.4 LTS中运行WeText项目的服务端

在《WeText项目:一个基于.NET实现的DDD、CQRS与微服务架构的演示案例》文章中,我介绍了自己用Visual Studio 2015(C# 6.0 with .NET Framework 4.6.1)开发的DDD/CQRS/微服务架构的案例项目:WeText。文章发出后反响很好…

es6 dsl与sql对比

【README】 1.本文总结了 dsl 与 sql的对比写法; 2.es采用 7.2.1 版本; 【1】创建es索引 1)新建一个数据库事务执行日志索引 put localhost:9200/txlog { "mappings" :{ "properties":{"APPNAME"…

echarts line 去掉最外围方框_干货 | 关于射频芯片最详细解读

传统来说,一部可支持打电话、发短信、网络服务、APP应用的手机,一般包含五个部分部分:射频部分、基带部分、电源管理、外设、软件。射频部分:一般是信息发送和接收的部分;基带部分:一般是信息处理的部分&am…

服务器性能指标(一)——负载(Load)分析及问题排查

转载自 服务器性能指标(一)——负载(Load)分析及问题排查平常的工作中,在衡量服务器的性能时,经常会涉及到几个指标,load、cpu、mem、qps、rt等。每个指标都有其独特的意义,很多时候…

HoloLens开发手记 - HoloLens shell概述 HoloLens shell overview

使用HoloLens时,shell是由你周围的世界和来自系统的全息图像构成。我们将这种空间成为混合世界(mixed world)。 shell包含了一个可以让你将全息图像和应用放置在世界中的开始菜单(Start Menu)。当一个应用已经被放置在…

【1】flink-source读取数据

【README】 本文记录了flink读取不同数据源的编码方式&#xff0c;数据源包括&#xff1b; 集合&#xff08;元素列表&#xff09;&#xff1b;文件kafka&#xff1b;自定义数据源&#xff1b; 本文使用的flink为 1.14.4 版本&#xff1b;maven依赖如下&#xff1a; <dep…

Oracle入门(二)之服务启动bat

转载自 批处理&#xff08;bat文件&#xff09;自动启动/关闭oracle服务 批处理&#xff08;bat文件&#xff09; 自动启动/关闭oracle服务 判断oracle 服务状态如果服务处于启动状态&#xff0c;就关闭服务&#xff1b;如果服务处于关闭状态&#xff0c;就启动服务。 ECHO OFF…

【2】flink数据流转换算子

【README】 本文记录了flink对数据的转换操作&#xff0c;包括 基本转换&#xff0c;map&#xff0c;flatMap&#xff0c;filter&#xff1b;滚动聚合&#xff08;min minBy max maxBy sum&#xff09;&#xff1b;规约聚合-reduce&#xff1b;分流&#xff1b;connect连接流…

第三篇 Entity Framework Plus 之 Query Cache

离上一篇博客&#xff0c;快一周&#xff0c;工作太忙&#xff0c;只能利用休息日来写一些跟大家分享&#xff0c;Entity Framework Plus 组件系列文章&#xff0c;之前已经写过两篇 第一篇 Entity Framework Plus 之 Audit 第二篇 Entity Framework Plus 之 Query Future 计划…

wireshark tcp抓包分析_网络分析系列之八_使用Wireshark抓包

通过前面的部分&#xff0c;我们对Wireshark界面主体内容有了大致了解。这一节主要介绍如何抓包&#xff0c;抓包后的界面显示&#xff08;因为Wireshark打开数据包后又是另一副界面&#xff09;。如何保存或导出抓取的报文等内容。第一次抓包现在可以开始你的第一次数据包捕获…

Oracle入门(五C)之68个系统变量的key和默认value

Oracle的68个系统变量的key和默认valueappinfo 为 OFF 并且已设置为 "SQL*Plus" arraysize 15 autocommit OFF autoprint OFF autorecovery OFF autotrace OFF blockterminator "." (hex 2e) btitle OFF 为下一条 SELECT 语句的前几个字符 …

【3】flink sink

【README】 本文记录了flink sink操作&#xff0c;输出目的存储器&#xff08;中间件&#xff09;包括 kafka&#xff1b;es&#xff1b;db&#xff1b;等等有很多&#xff1b;本文只给出了 sink2kafka的代码&#xff1b; 本文使用的flink为 1.14.4 版本&#xff1b; 本文部…