Reface.AppStarter 向应用层提供以下几项 核心 功能

  • 以模块化组织你的应用程序
  • 自动注册组件至 IOC 容器
  • 自动映射配置文件至配置类
  • 在模块定义类中额外追加组件至 IOC 容器
  • 在模块定义类中额外追加配置类
  • 事件总线

这些功能允许让开发者将功能拆分至各个小粒度模块,

当使用某个模块时,只需要向模块添加一个依赖,即可开启所有功能,

实现了整个模块的开箱即用。


本文将介绍 Reface.AppStarter 中最常用的三个功能 自动注册组件至 IOC 容器自动映射配置文件模块化

自动注册组件至 IOC 容器

使用 IOC 容器 往往分为两个阶段

  • 配置阶段
  • 使用阶段

配置阶段 我们可能会选择 配置文件对所有依赖的程序集反射对指定程序反射硬编码 等方式对组件进行 注册

对所有依赖的程序集反射 ,怎么看都是一种即笨重又有些呆板的方法。

然而另外几个方案在多模块化的项目里中 ,

也无法很好的工作,

它们各自需要在系统启动时,明确一些信息 :

  • 一共需要读取哪些配置文件,这些文件在各个子模块的哪儿
  • 一共需要对哪些程序集进行反射
  • 那些负责硬编码注册的类型都在哪儿

如果上述的信息没有被收集完整,那么程序会因为没有注册全部组件而无法正确运行。


事实上

在大多数情况下,开发者在编写一个 接口 和一个 实现 时,就已经确定 注册关系

只有那些可能面临 策略模式 ,或者存在多客户端适配的情况下,这种 注册关系 无法确定。

所以通过 Attribute 加 扫描,是一种很好的 自动化注册 手段。

假定我们需要实现下面的接口

  1. // Services/IUserService.cs
  2. public interface IUserService
  3. {
  4. void CreateUser(User user);
  5. }

实现过程大致如下

  1. // Services/DefaultUserService.cs
  2. public class DefaultUserService : IUserService
  3. {
  4. private readonly IRepository<User> userRepo ;
  5. public DefaultUserService(IRepository<User> userRepo)
  6. {
  7. this.userRepo = userRepo;
  8. }
  9. public void CreateUser(User user)
  10. {
  11. this.userRepo.Insert(user);
  12. }
  13. }

使用 Reface.AppStarter ,你不再需要编写额外的代码将这个 DefaultUserService 注册到 IUserService 上。

你只需要为 DefaultUserService 添加一个 ComponentAttribute

  1. // Services/DefaultUserService.cs
  2. [Component]
  3. public class DefaultUserService : IUserService
  4. {
  5. // ...
  6. }

这个 特征 就是通知 Reface.AppStarter 将该类型注册到 IOC 容器 中,并注册到它所有实现的接口类型上。


在由 Reface.AppStarter 构建的系统中,程序不是单纯的由 程序集 组成,而是由 应用模块 组成。

应用模块 不仅包含了 程序集 原有的功能,还能够体系与其它 应用模块 的依赖关系。

现在我们为刚才 DefaultUserService 所在的 程序集 编写一个 应用模块 的类型。

  1. // UserAppModule.cs
  2. [ComponentScanAppModule]
  3. public class UserAppModule : AppModule
  4. {
  5. }

这就是一个 用户应用模块 ( 所有的 应用模块 应当从 AppModule 继承 ),

它依赖了一个 ComponentScanAppModule应用模块

ComponentScanAppModule 会将 目标应用模块 中标记了 ComponentAttribute 的类型注册到 IOC 容器中。

运行程序

  1. public static void Main(String[] args)
  2. {
  3. var app = AppSetup.Start<UserAppModule>();
  4. IUserService service = app.CreateComponent<IUserService>();
  5. // you can use service now;
  6. }

除了直接启动 UserAppModule ,

也可以将 UserAppModule 加到别的 应用模块 上,这个 自动注册 同样有效。

基于这样的方式, UserAppModule 完全可以开箱即用。

也可以说,任何一个 应用模块 都可以开箱即用。

自动映射配置文件

配置文件总是存在的, .NetFramework 提供了一整套 Configuration 方案。

但是这个方案略显笨重,并且在配置过程完全没有提示,必须依赖大量的文档说明。

很明显 JSONXML 轻巧很多,

并且还有 JsonSchema 可以向 IDE 提供提示功能。

所以 Reface.AppStarter 选择了 JSON 作为配置文件的格式 ,

Reface.AppStarter 会读取一个包含了所有配置的 JSON 文件,

将配置中的值映射的 对应 的类型和属性中,

并将这些 类型 以单例的模式注册到 IOC 容器中。


UserAppModule 为例,我们为其开发一个 配置类

配置类 就是 Reface.AppStarter 在解析 JSON 文件后反序列化的目标类型。

为一个类型添加 ConfigAttribute 就会通知 Reface.AppStarter : "嘿,这有一个配置类"

下面的例子表示,我们可以通过配置文件指定 根用户的信息

  1. // Configs/UserConfig
  2. [Config("User")]
  3. public class UserConfig
  4. {
  5. public string RootUserName { get; set; } = "admin";
  6. public string RootUserPassword { get; set; } = "888888";
  7. }

ConfigAttribute 的构造函数中指定的 User 表示从配置文件的 User 节点中读取配置,配置文件大至如下:

  1. {
  2. "User" : {
  3. "RootUserName" : "ROOT",
  4. "RootUserPassword" : "123456789"
  5. }
  6. }

如果没有配置文件,或者配置文件中没有编写 User 则会使用属性中指定的默认值将配置类实例注册到 IOC 容器 中。

通过构造函数注入配置类就可以使用它们。

  1. // Services/DefaultUserService.cs
  2. public class DefaultUserService : IUserService
  3. {
  4. private readonly IRepository<User> userRepo;
  5. private readonly UserConfig userConfig;
  6. public DefaultUserService(IRepository<User> userRepo, UserConfig userConfig)
  7. {
  8. this.userRepo = userRepo;
  9. this.userConfig = userConfig;
  10. }
  11. public void CreateUser(User user)
  12. {
  13. if(user.Name == userConfig.RootUserName)
  14. throw new SomeException("无效的用户名,不能创建该用户");
  15. this.userRepo.Insert(user);
  16. }
  17. }

ComponentScanAppModule 一样,需要为 UserAppModule 添加一样依赖来开启 自动映射配置文件 的功能。

  1. // UserAppModule.cs
  2. [ComponentScanAppModule] // 开启自动扫描注册组件
  3. [AutoConfigAppModule] // 开启自动映射配置文件
  4. public class UserAppModule : AppModule
  5. {
  6. }

现在启动 UserAppModule

或者将 UserAppModule 添加到其它 应用模块 的依赖项中,

这些功能都会被启用。

AppSetup.Start() 默认读取 app.json 文件,

若配置文件不存在,则直接使用 配置类 的默认属性值。

关于配置智能提示

通过 AppSetup.Start<T>() 运行程序后,会在输出目录下产生一个 app.schema.json 文件。

为你的 app.json 添加 $schema 属性,值指向 app.schema.json 文件,就可以得到智能提示功能:

你也可以通过上图显示的属性关闭生成 app.schema.json 的功能。


相关链接

Reface.AppStarter 基本示例的更多相关文章

  1. Reface.AppStarter 框架初探

    Reface.AppStarter 是一种基于 .NetFramework 的应用程序启动模式,使用该启动模式,你可以轻松的得到以下功能 : IOC / DI 自动注册与装配 简化配置 垂直模块化你的 ...

  2. Reface.AppStarter 类型扫描 —— 获得系统中所有的实体类型

    类型扫描 是 Reface.AppStarter 提供的最基本.最核心的功能. AutoConfig , ComponentScan 等功能都是基于该功能完成的. 每一个使用 Reface.AppSt ...

  3. 事件总线功能库,Reface.EventBus 详细使用教程

    Reface.AppStarter 中的事件总线功能是通过 Reface.EventBus 提供的. 参考文章 : Reface.AppStarter 框架初探 使用 Reface.EventBus ...

  4. Reface.NPI 方法名称解析规则详解

    在上次的文章中简单介绍了 Reface.NPI 中的功能. 本期,将对这方法名称解析规则进行详细的解释和说明, 以便开发者可以完整的使用 Reface.NPI 中的各种功能. 基本规则 方法名称以 I ...

  5. EF 太重,MyBatis 太轻,ORM 框架到底怎么选 ?

    以 EF 为代表的基于 Linq 的 ORM 框架总是 很重. 他们的功能早已超出了一个 ORM 的范畴, ORM 是 Object Relational Mapping ,从名字上看,其初衷是将 数 ...

  6. 如何将 .NetFramework WebApi 按业务拆分成多个模块

    在 .NetFramework 中使用 WebApi ,在不讨论 微服务 的模式下,大部分都是以层来拆分库的 : 基础设施 数据存储层 服务层 WeApi 层 一些其它的功能库 项目结构可能会像下面这 ...

  7. 代理模式是什么?如何在 C# 中实现代理模式

    代理模式 并不是日常开发工作中常常用到的一种设计模式,也是一种不易被理解的一种设计模式.但是它会广泛的应用在系统框架.业务框架中. 定义 它的 定义 就如其它同大部分 设计模式 的定义类似,即不通俗也 ...

  8. Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)

    本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...

  9. .NET跨平台之旅:将示例站点升级至 ASP.NET Core 1.1

    微软今天在 Connect(); // 2016 上发布了 .NET Core 1.1 ,ASP.NET Core 1.1 以及 Entity Framework Core 1.1.紧跟这次发布,我们 ...

随机推荐

  1. 拒绝降权!教你用 Python 确保制作的短视频独一无二

    1. 场景 前段时间有人私信我,说自己辛辛苦苦剪辑的短视频,上传到某平台后,由于播放量太大,收到 降权 的通知,直接导致这个账号废掉了! 其实,各大视频平台都有自己的一套鉴别算法,针对视频的二次创作, ...

  2. 果然学习好是有道理的,学习Mysql与正则表达式笔记

    正则表达式是用来匹配文本的特殊的字符集合,将一个正则表达式与文本串进行比较,Mysql中用where子句提供支持,正则表达式关键字:regexp1.使用‘|’匹配两个串中的一个 2.使用‘[]’匹配几 ...

  3. cc40a_demo_Cpp_智能指针c++_txwtech

    //40_21days_Cpp_智能指针c++_cc40a_demo.cpp_txwtech //智能指针.auto_ptr类//*常规指针-容易产生内存泄漏,内存被占满,程序就死机,或者系统死机// ...

  4. Java学习笔记6(集合类)

    集合类 集合按照其存储结构可以分为两大类,即单列集合Collection和双列集合Map. Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,有List和Set两个重要子接口 ...

  5. Spring学习笔记下载

    动力节点的spring视频教程相当的经典:下载地址 https://pan.baidu.com/s/1eTSOaae

  6. 10、一个action中处理多个方法的调用第二种方法method的方式

    在实际的项目中,经常采用现在的第二种方式在struct.xml中采用清单文件的方式 我们首先来看action package com.bjpowernode.struts2; import com.o ...

  7. java scoket Blocking 阻塞IO socket通信一

    package bhz.bio; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; p ...

  8. 我的.net开发百宝箱

    一.Resharper http://www.jetbrains.com/resharper/ 最强悍的VisualStudio的插件,它包括一系列丰富的,能大大增加C#和Visual Basic . ...

  9. 开发中如何让本地host和代理共存?

    开发中若遇到了需要相同域名的情况,比如利用cookie共享的sso策略,可以设置本地host映射到开发服务.设置域名,生效,正常开发. 但在公司中可能是内网,请求都需要经过代理,这时候可能会发现设置h ...

  10. 如何判断一个String字符串不为空或这不为空字符串

    如何判断一个String字符串不为空或这不为空字符串 转载兵哥LOVE坤 最后发布于2018-07-27 00:00:05 阅读数 5144  收藏 展开 1.校验不为空:   String str ...