探索ABP基础架构-下
配置应用程序
ASP.NET Core 的配置系统提供了一个基于键值对的配置方法。它是一个可扩展的系统,可以从各种资源中读取键值对,例如 JSON 设置文件、环境变量、命令行参数等等。
设置配置值
默认使用appsettings.json
文件是配置的最简单方法。假设我们正在构建一个使用 Azure 发送 SMS 的服务,并且我们需要以下配置值:
Sender
: 发件人号码ConnectionString
: 你的 Azure 资源的连接字符串
我们可以在appsettings.json
文件的配置部分定义这些:
{
...
"AzureSmsService": {
"Sender": "+901112223344",
"ConnectionString": "..."
}
}
这里的键名是完全任意的,只要您在代码中使用相同的键,您就可以轻松地读取它们的值。
读取配置值
您可以在需要读取配置值的地方注入IConfiguration
以使用该服务。例如,我们可以在 AzureSmsService
中获取Azure 配置值用于发送 SMS:
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Volo.Abp.DependencyInjection;
namespace SmsSending
{
public class AzureSmsService : ISmsService, ITransientDependency
{
private readonly IConfiguration _configuration;
public AzureSmsService(IConfiguration configuration)
{
_configuration = configuration;
}
public async Task SendAsync(string phoneNumber, string message)
{
string sender = _configuration["AzureSmsService:Sender"];
string ConnectionString = _configuration["AzureSmsService:ConnectionString"];
//TODO: Use Azure to send the SMS message
}
}
}
IConfiguration
服务也可用于ConfigureServices
中:
public override void ConfigureServices(ServiceConfigurationContext context)
{
IConfiguration configuration = context.Services.GetConfiguration();
string sender = configuration["AzureSmsService:Sender"];
}
这里,我们可以在服务注入之前访问配置值。
以上的配置方式固然方便,但是,如果您正在构建一个可重用的库,则选项模式可能是更好的方法,因为它是类型安全。
实现选项模式
为了使用选项模式,我们使用一个普通的类(有时称为POCO–Plain Old C# Object),我们从如何定义、配置和使用配置开始。
定义选项类
选项类是一个简单的类。我们为 Azure SMS 服务定义一个选项类,如以下代码块所示:
public class AzureSmsServiceOptions
{
public string Sender { get; set; }
public string ConnectionString { get; set; }
}
将后缀Options
添加到选项类是一种约定。
配置选项
您可以在模块的ConfigureServices
方法中配置,可以使用IServiceCollection.Configure
的扩展方法为任何选项类设置值。看下下面的代码块是如何配置的:
[DependsOn(typeof(SmsSendingModule))]
public class MyStartupModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.Configure<AzureSmsServiceOptions>(options =>
{
options.Sender = "+901112223344";
options.ConnectionString = "...";
});
}
}
context.Services.Configure
方法是获取选项类的通用方法。它还需要一个委托来设置选项值。在此示例中,我们通过在指定的 lambda 表达式中设置Sender
和ConnectionString
属性来进行配置。
AbpModule
基类提供了一个Configure
方法作为context.Services.Configure
方法的快捷方式,因此您可以重写代码如下:
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AzureSmsServiceOptions>(options =>
{
options.Sender = "+901112223344";
options.ConnectionString = "...";
});
}
你应该看到了一点点区别了吧?
使用配置选项值
ASP.NET Core 提供了一个IOptions<T>
接口来注入选项类。我们使用AzureSmsServiceOptions
重写AzureSmsService
里的IConfiguration
服务,如以下代码块所示:
public class AzureSmsService : ISmsService, ITransientDependency
{
private readonly AzureSmsServiceOptions _options;
public AzureSmsService(IOptions<AzureSmsServiceOptions> options)
{
_options = options.Value;
}
public async Task SendAsync(string phoneNumber, string message)
{
string sender = _options.Sender;
string ConnectionString = _options.ConnectionString;
//TODO...
}
}
我们注入IOptions<AzureSmsServiceOptions>
并使用其Value
属性来获取配置值。IOptions<T>
接口定义在Microsoft.Extensions.Options
包里,是一种标准的选项类注入方式,如果你直接注入AzureSmsServiceOptions
类,你会得到一个依赖注入异常。所以要通过IOptions<T>
把选项类包裹起来.
上面只是简单地定义、配置和使用了这些选项。如果我们想结合配置系统来设置选项该怎么办?
首先,我们用IConfiguration
读取配置,并设置选项值:
[DependsOn(typeof(SmsSendingModule))]
public class MyStartupModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AzureSmsServiceOptions>(options =>
{
options.Sender = configuration\["AzureSmsService:Sender"\];
options.ConnectionString = configuration\["AzureSmsService:ConnectionString"\];
});
}
}
我们通过上下文的context.Services.GetConfiguration()
方法获得IConfiguration
接口,然后进行赋值操作。
由于这种用法很常见,我们可以重写一下代码,如下块所示:
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<AzureSmsServiceOptions>(configuration.GetSection("AzureSmsService"));
}
[success] 翻译点评:虽然改动量很小,但是非常漂亮,可见作者精益求精的态度。
使用这种用法,配置代替了委托操作,它通过命名约定自动将配置键与选项类的属性进行匹配。如果AzureSmsService
未在配置中定义,则此代码也不会影响选项。
选项模式为开发人员提供了更大的灵活性:他们可以从IConfiguration
或者其他数据源进行选项设置。
[success] 提示:默认情况下从配置中设置选项
如果您正在构建可重用模块,最好尽可能从配置中设置选项。也就是说,您可以将前面的代码写入您的模块中。这样,开发人员可以直接从appsettings.json
文件中配置他们的模块。
ASP.NET Core 和 ABP 选项
ASP.NET Core 和 ABP 框架都集中预先使用选项模式配置选项。
以下示例显示了在 ABP 框架中配置选项:
Configure<AbpAuditingOptions>(options =>
{
options.IgnoredTypes.Add(typeof(ProductDto));
});
AbpAuditingOptions
由 ABP 框架的审计日志系统定义。我们正在添加一个类型,用于在审计日志中忽略ProductDto
。
下一个示例显示在 ASP.NET Core 中配置选项:
Configure<MvcOptions>(options =>
{
options.RespectBrowserAcceptHeader = true;
});
MvcOptions
由 ASP.NET Core 内部定义,用于配置 ASP.NET Core MVC 框架的行为。
选项类中的复杂类型
请注意,AbpAuditingOptions.IgnoredTypes
是一个的Type
列表,它不是在appsettings.json
文件中定义的那种简单原始类型,这是选项模式的好处之一:您可以定义具有复杂类型的属性甚至回调动作。
配置和选项系统提供了一种便捷的方式来配置服务的行为。
日志系统
日志记录是每个应用的基础设施。ASP.NET Core 提供了一个简单而高效的日志系统。它可以与流行的日志库集成,例如 NLog、Log4Net 和 Serilog。
Serilog 是一个广泛使用的库,它为日志目标提供了许多选项,包括控制台、文本文件和 Elasticsearch。ABP 启动模板带有预安装和配置的 Serilog 库。它将日志写入应用的Logs
文件夹中,如果需要,您可以配置 Serilog 以将日志写入不同的目标(所有配置都包含在启动模板中)。请参考 Serilog 的官方文档来配置 Serilog 选项。
Serilog 不是 ABP 框架的核心依赖,因此,我们可以轻松使用其他提供商进行替换。
该ILogger<T>
接口用于在 ASP.NET Core 中写入日志,T
通常是您的服务类型。
下面是一个写入日志的示例服务:
public class AzureSmsService : ISmsService, ITransientDependency
{
private readonly ILogger<AzureSmsService> _logger;
public AzureSmsService(ILogger<AzureSmsService> logger)
{
_logger = logger;
}
public async Task SendAsync(string phoneNumber, string message)
{
_logger.LogInformation($"Sending SMS to {phoneNumber}: {message}");
//TODO...
}
}
该类在其构造函数中注入ILogger<AzureSmsService>
服务并使用LogInformation
方法将日志写入日志系统。
ILogger
接口上有更多的方法可以写入不同严重级别的日志,例如LogError和LogDebug。有关所有详细信息,请参阅 ASP.NET Core 的文档日志系统。
概括
本章介绍了 ASP.NET Core 和 ABP 框架的核心模块。
你已经了解了如何使用Startup
类、配置系统和选项模式来配置 ASP.NET Core 和 ABP 框架服务。
ABP 提供了一个模块化系统,相比 ASP.NET Core 的初始化和配置,ABP支持创建多个模块,其中每个模块支持独立的初始化和配置。通过这种方式,您可以将应用拆分为多个模块,以更好地方式组织代码或创建在不同应用中可重用的模块。
依赖注入系统是ASP.NET Core 最基本的基础设施。一个服务通常使用依赖注入系统消费其他服务。这里介绍了依赖注入系统的基本方面,并解释了 ABP 如何简化服务注册。
下一章重点介绍数据访问基础架构,这是业务应用程序的一个重要方面。我们将看到 ABP 框架如何标准化定义实体和使用存储库来抽象和执行数据库操作,同时自动化数据库连接和事务管理。
探索ABP基础架构-下的更多相关文章
- 探索ABP基础架构
为了了解应用程序是如何配置和初始化,本文将探讨ASP.NET Core和ABP框架最基本的构建模块.我们将从 ASP.NET Core 的 Startup类开始了解为什么我们需要模块化系统,以及 AB ...
- ABP框架之——数据访问基础架构
大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享阅读心得,希望我的文章能成为你成长路上的一块垫脚石,我们一起精进. 几乎所有的业务应用程序都要适用一种数据库基础架构,用来实现数据访问逻辑,以便从数 ...
- 一、项目基础架构(附GitHub地址)——以ABP为基础架构的一个中等规模的OA开发日志
前言: 最近园子里ABP炒的火热.看了几篇对于ABP的介绍后,深感其设计精巧,实现优雅.个人感觉,ABP或ABP衍生品的架构设计,未来会成为中型Net项目的首选架构模式.如果您还不了解ABP是什么,有 ...
- Pass Infrastructure基础架构(下)
Pass Infrastructure基础架构(下) pass注册 PassRegistration该类在示例中简要显示了各种pass类型的定义 .该机制允许注册pass类,以便可以在文本pass管 ...
- 云计算服务模型,第 1 部分: 基础架构即服务(IaaS)
英文原文:Cloud computing service models, Part 1: Infrastructure as a Service 本文介绍三个云类别中的第一个:基础架构即服务(infr ...
- 如何使用 Docker、ECS、Terraform 重建基础架构?
早期 Segment 基础架构普遍组合在一起.我们通过 AWS 界面设定实例,使用许多闲散的 AMI,并且采用三种不同的部署方式. 然而随着商业的飞速发展,工程师团队的规模不断扩大,基础架构的复杂度也 ...
- 微服务架构下分布式事务解决方案——阿里GTS
1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这样可以降低开发难度.增强扩展性.便于敏捷开发.当前被越来越多的开发者推崇,很多互联网行业巨头.开源社区等都开始了微服务 ...
- DCOS :私有云的物理基础架构管理引擎
https://cloud.tencent.com/developer/article/1005598 一.引言 云计算经过多年的发展,逐渐从概念到渐为人认知.到接受.到现在全行业拥抱上云,云的客户也 ...
- 微服务架构下分布式事务解决方案——阿里云GTS
https://blog.csdn.net/jiangyu_gts/article/details/79470240 1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这 ...
随机推荐
- 学习SVN01
SVN服务器搭建实录 第一章 SVN介绍 1.1 什么是SVN(subversion) SVN是近年来崛起的非常优秀的版本管理工具,与CVS管理工具一样,SVN是一个固态的跨平台的开源的版本控制 ...
- 运筹学之"概率"和"累计概率"和"谁随机数"
概率 = 2/50 = 0.2 累计概率 = 上个概率加本次概率 案例1 概率=销量天数 / 天数 = 2 /100 = 0.02 累计概率 = 上个概率加本次概率 = 0.02 +0.03 = 0. ...
- js技术之截取substring(int,int)
案例:把所有单词以空格为分割并将首字母转为大写 <!DOCTYPE html><html lang="en"><head> <meta c ...
- PID控制算法的C语言实现
参考: PID控制器开发笔 浅谈位置式PID 专家PID控制在快速系统中的仿真及应用(这篇了论文介绍的积分分离PID.专家PID(脚本实现和simulink实现)很详细) PID控制算法的C语言实现一 ...
- 制作任意波形发生器MAX038
- html 不常用标签介绍
文本元素 <wbr> 如果单词太长,或者您担心浏览器会在错误的位置换行,那么您可以使用 <wbr> 元素来添加 Word Break Opportunity(单词换行时机).英 ...
- 探讨:微信小程序应该如何设计
微信小程序公测后,开发者非常热情,都有很高的期待,都想抓住这一波红利.但是热情背后需要冷静,我们需要搞清楚两个问题: 微信想要我们做什么?微信小程序可以做什么? 微信想要我们做什么? 首先来弄清楚微信 ...
- vue重构--H5--canvas实现粒子时钟
上一篇文章讲解了如何用js+canvas实现粒子时钟,本篇文章 ,主要是使用vue重构,让它在vue也能使用. 我们使用简单的方式重构,不使用vue工程,先加入vue cdn的地址,如下: <s ...
- JavaScript 中 append()、prepend()、after()、before() 的区别
内容 append().prepend().after().before() 的区别 jQuery 操作 DOM 之添加节点 方法名 作用 $(selector).append() 指定元素内部添加, ...
- setTimeout中第一个参数
永远不要传递字符串作为setTimeout的第一个参数!!!记住第一个参数只允许函数,或者匿名函数!因为传递字符串有陷阱啊!!它就是披着羊皮的eval啊!!而且上下文会变成全局啊!! 第一个参数为可执 ...