Reface.AppStarter 基本示例
Reface.AppStarter 向应用层提供以下几项 核心 功能
- 以模块化组织你的应用程序
- 自动注册组件至 IOC 容器
- 自动映射配置文件至配置类
- 在模块定义类中额外追加组件至 IOC 容器
- 在模块定义类中额外追加配置类
- 事件总线
这些功能允许让开发者将功能拆分至各个小粒度模块,
当使用某个模块时,只需要向模块添加一个依赖,即可开启所有功能,
实现了整个模块的开箱即用。
本文将介绍 Reface.AppStarter 中最常用的三个功能 自动注册组件至 IOC 容器 、 自动映射配置文件 和 模块化。
自动注册组件至 IOC 容器
使用 IOC 容器 往往分为两个阶段
- 配置阶段
- 使用阶段
在 配置阶段 我们可能会选择 配置文件 、对所有依赖的程序集反射 、 对指定程序反射 、 硬编码 等方式对组件进行 注册 。
对所有依赖的程序集反射 ,怎么看都是一种即笨重又有些呆板的方法。
然而另外几个方案在多模块化的项目里中 ,
也无法很好的工作,
它们各自需要在系统启动时,明确一些信息 :
- 一共需要读取哪些配置文件,这些文件在各个子模块的哪儿
- 一共需要对哪些程序集进行反射
- 那些负责硬编码注册的类型都在哪儿
如果上述的信息没有被收集完整,那么程序会因为没有注册全部组件而无法正确运行。
事实上
在大多数情况下,开发者在编写一个 接口 和一个 实现 时,就已经确定 注册关系 。
只有那些可能面临 策略模式 ,或者存在多客户端适配的情况下,这种 注册关系 无法确定。
所以通过 Attribute 加 扫描,是一种很好的 自动化注册 手段。
假定我们需要实现下面的接口
// Services/IUserService.cs
public interface IUserService
{
void CreateUser(User user);
}
实现过程大致如下
// Services/DefaultUserService.cs
public class DefaultUserService : IUserService
{
private readonly IRepository<User> userRepo ;
public DefaultUserService(IRepository<User> userRepo)
{
this.userRepo = userRepo;
}
public void CreateUser(User user)
{
this.userRepo.Insert(user);
}
}
使用 Reface.AppStarter ,你不再需要编写额外的代码将这个 DefaultUserService 注册到 IUserService 上。
你只需要为 DefaultUserService 添加一个 ComponentAttribute 。
// Services/DefaultUserService.cs
[Component]
public class DefaultUserService : IUserService
{
// ...
}
这个 特征 就是通知 Reface.AppStarter 将该类型注册到 IOC 容器 中,并注册到它所有实现的接口类型上。
在由 Reface.AppStarter 构建的系统中,程序不是单纯的由 程序集 组成,而是由 应用模块 组成。
应用模块 不仅包含了 程序集 原有的功能,还能够体系与其它 应用模块 的依赖关系。
现在我们为刚才 DefaultUserService 所在的 程序集 编写一个 应用模块 的类型。
// UserAppModule.cs
[ComponentScanAppModule]
public class UserAppModule : AppModule
{
}
这就是一个 用户应用模块 ( 所有的 应用模块 应当从 AppModule 继承 ),
它依赖了一个 ComponentScanAppModule 的 应用模块 。
ComponentScanAppModule 会将 目标应用模块 中标记了 ComponentAttribute 的类型注册到 IOC 容器中。
运行程序
public static void Main(String[] args)
{
var app = AppSetup.Start<UserAppModule>();
IUserService service = app.CreateComponent<IUserService>();
// you can use service now;
}
除了直接启动 UserAppModule ,
也可以将 UserAppModule 加到别的 应用模块 上,这个 自动注册 同样有效。
基于这样的方式, UserAppModule 完全可以开箱即用。
也可以说,任何一个 应用模块 都可以开箱即用。
自动映射配置文件
配置文件总是存在的, .NetFramework 提供了一整套 Configuration 方案。
但是这个方案略显笨重,并且在配置过程完全没有提示,必须依赖大量的文档说明。
很明显 JSON 比 XML 轻巧很多,
并且还有 JsonSchema 可以向 IDE 提供提示功能。
所以 Reface.AppStarter 选择了 JSON 作为配置文件的格式 ,
Reface.AppStarter 会读取一个包含了所有配置的 JSON 文件,
将配置中的值映射的 对应 的类型和属性中,
并将这些 类型 以单例的模式注册到 IOC 容器中。
以 UserAppModule 为例,我们为其开发一个 配置类,
配置类 就是 Reface.AppStarter 在解析 JSON 文件后反序列化的目标类型。
为一个类型添加 ConfigAttribute 就会通知 Reface.AppStarter : "嘿,这有一个配置类"。
下面的例子表示,我们可以通过配置文件指定 根用户的信息
// Configs/UserConfig
[Config("User")]
public class UserConfig
{
public string RootUserName { get; set; } = "admin";
public string RootUserPassword { get; set; } = "888888";
}
ConfigAttribute 的构造函数中指定的 User 表示从配置文件的 User 节点中读取配置,配置文件大至如下:
{
"User" : {
"RootUserName" : "ROOT",
"RootUserPassword" : "123456789"
}
}
如果没有配置文件,或者配置文件中没有编写 User 则会使用属性中指定的默认值将配置类实例注册到 IOC 容器 中。
通过构造函数注入配置类就可以使用它们。
// Services/DefaultUserService.cs
public class DefaultUserService : IUserService
{
private readonly IRepository<User> userRepo;
private readonly UserConfig userConfig;
public DefaultUserService(IRepository<User> userRepo, UserConfig userConfig)
{
this.userRepo = userRepo;
this.userConfig = userConfig;
}
public void CreateUser(User user)
{
if(user.Name == userConfig.RootUserName)
throw new SomeException("无效的用户名,不能创建该用户");
this.userRepo.Insert(user);
}
}
与 ComponentScanAppModule 一样,需要为 UserAppModule 添加一样依赖来开启 自动映射配置文件 的功能。
// UserAppModule.cs
[ComponentScanAppModule] // 开启自动扫描注册组件
[AutoConfigAppModule] // 开启自动映射配置文件
public class UserAppModule : AppModule
{
}
现在启动 UserAppModule
或者将 UserAppModule 添加到其它 应用模块 的依赖项中,
这些功能都会被启用。
AppSetup.Start() 默认读取 app.json 文件,
若配置文件不存在,则直接使用 配置类 的默认属性值。
关于配置智能提示
通过 AppSetup.Start<T>() 运行程序后,会在输出目录下产生一个 app.schema.json 文件。
为你的 app.json 添加 $schema 属性,值指向 app.schema.json 文件,就可以得到智能提示功能:
你也可以通过上图显示的属性关闭生成 app.schema.json 的功能。
相关链接
Reface.AppStarter 基本示例的更多相关文章
- Reface.AppStarter 框架初探
Reface.AppStarter 是一种基于 .NetFramework 的应用程序启动模式,使用该启动模式,你可以轻松的得到以下功能 : IOC / DI 自动注册与装配 简化配置 垂直模块化你的 ...
- Reface.AppStarter 类型扫描 —— 获得系统中所有的实体类型
类型扫描 是 Reface.AppStarter 提供的最基本.最核心的功能. AutoConfig , ComponentScan 等功能都是基于该功能完成的. 每一个使用 Reface.AppSt ...
- 事件总线功能库,Reface.EventBus 详细使用教程
Reface.AppStarter 中的事件总线功能是通过 Reface.EventBus 提供的. 参考文章 : Reface.AppStarter 框架初探 使用 Reface.EventBus ...
- Reface.NPI 方法名称解析规则详解
在上次的文章中简单介绍了 Reface.NPI 中的功能. 本期,将对这方法名称解析规则进行详细的解释和说明, 以便开发者可以完整的使用 Reface.NPI 中的各种功能. 基本规则 方法名称以 I ...
- EF 太重,MyBatis 太轻,ORM 框架到底怎么选 ?
以 EF 为代表的基于 Linq 的 ORM 框架总是 很重. 他们的功能早已超出了一个 ORM 的范畴, ORM 是 Object Relational Mapping ,从名字上看,其初衷是将 数 ...
- 如何将 .NetFramework WebApi 按业务拆分成多个模块
在 .NetFramework 中使用 WebApi ,在不讨论 微服务 的模式下,大部分都是以层来拆分库的 : 基础设施 数据存储层 服务层 WeApi 层 一些其它的功能库 项目结构可能会像下面这 ...
- 代理模式是什么?如何在 C# 中实现代理模式
代理模式 并不是日常开发工作中常常用到的一种设计模式,也是一种不易被理解的一种设计模式.但是它会广泛的应用在系统框架.业务框架中. 定义 它的 定义 就如其它同大部分 设计模式 的定义类似,即不通俗也 ...
- Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)
本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...
- .NET跨平台之旅:将示例站点升级至 ASP.NET Core 1.1
微软今天在 Connect(); // 2016 上发布了 .NET Core 1.1 ,ASP.NET Core 1.1 以及 Entity Framework Core 1.1.紧跟这次发布,我们 ...
随机推荐
- Android学习笔记ActionView
概念 案例 1.布局文件 activity_main.xml <?xml version="1.0" encoding="utf-8"?> < ...
- Spring IOC原理补充(循环依赖、Bean作用域等)
文章目录 前言 正文 循环依赖 什么是循环依赖? Spring是如何解决循环依赖的? 作用域实现原理以及如何自定义作用域 作用域实现原理 自定义Scope BeanPostProcessor的执行时机 ...
- Centos安装redis详解
redis官方网站对redis的安装已有介绍,但没有redis环境的安装,redis自动启动服务安装等等: redis官网:https://redis.io 本文以centos6为基础安装redis ...
- Postman之API测试使用全指南
Postman Postman是一个可扩展的API开发和测试协同平台工具,可以快速集成到CI/CD管道中.旨在简化测试和开发中的API工作流. Postman 工具有 Chrome 扩展和独立客户端, ...
- docker推送镜像到私有仓库
配置私有仓库源 私有仓库地址:registry.supos.ai 修改/etc/docker/daemon.json文件,增加insecure-registries,如下所示: { "ins ...
- typeof、instanceof与constructor
typeof返回一个表达式的数据类型的字符串,返回结果为js基本的数据类型,包括number,boolean,string,object,undefined,function. 语法: typeof( ...
- SQL注入基础原理
Web安全: 三层架构(3-tier architecture) 通常意义上就是将整个业务应用划分为: 界面层(User Interface layer) 业务逻辑层(Business Logic L ...
- return zero,or ,return non-zero
it may return a value to its caller, which is in effect the environment in which the program was exe ...
- 写出Python中列表、元祖、字典、字符串的至少5种以上的方法
1.列表 常用方法 作用 参数 append(data) 在尾部添加数据 data-加入到列表中的数据 insert(idx,data) 在指定位置添加数据 idx-索引 data-数据 ext ...
- Oracle Solaris 10下gdb安装(附安装包)
文章目录 1. 背景说明 2. gdb相关包 3. gdb安装 3.1 上传资源 3.2 解压 3.3 安装 3.4 环境变量 4. 位数确认 5. 验证可用性 1. 背景说明 本文承接Oracle ...