ABP vNext系列文章04---DynamicClient动态代理
一、动态代理在ABP系统中的应用
1、它主要在做什么事件
之前开发系统想要在后台调用别的服务都是用HttpClient发起请求,在abp vnext中不需要我们这样做了,
你只要知道服务调用的接口方法,就像调用本地代码一样调用接口,abp会动态生成一个http请求
这样,我们就引出了一个概念叫:动态 C# API 客户端
定义:ABP可以自动创建C# API 客户端代理来调用远程HTTP服务(REST APIS).通过这种方式,你不需要通过 HttpClient 或者其他低级的HTTP功能调用远程服务并获取数据.
2、如何申明一个远程的api接口
定义一个接口,只有一个条件:必须实现IRemoteService接口:
public interface IBookAppService : IApplicationService
{
Task<List<BookDto>> GetListAsync();
}
为了能自动被发现,你的接口需要实现IRemoteService接口.由于IApplicationService继承自IRemoteService接口.所以IBookAppService完全满足这个条件.
在你的服务中实现这个类,你可以使用auto API controller system将你的服务暴漏为一个REST API 端点.
3、添加 Volo.Abp.Http.Client nuget包
Install-Package Volo.Abp.Http.Client
增加的层为 HttpApi.Client
[DependsOn(typeof(AbpHttpClientModule))] //添加依赖
public class MyClientAppModule : AbpModule
{
}
4、创建客户端代理了.
例如:
[DependsOn(
typeof(AbpHttpClientModule), //用来创建客户端代理
typeof(MyApplicationContractsModule) //包含应用服务接口
)]
public class MyClientAppModule : AbpModule
{
private const string ProductRemoteServiceName = "ProductService";
public override void ConfigureServices(ServiceConfigurationContext context)
{
//创建动态客户端代理
context.Services.AddHttpClientProxies(
typeof(MyApplicationContractsModule).Assembly,ProductRemoteServiceName
);
}
}
AddHttpClientproxies方法获得一个程序集,找到这个程序集中所有的服务接口,创建并注册代理类.我们所有要调用的接口都是程序集 MyApplicationContractsModule 中的。
5、修改配置文件
appsettings.json文件中的RemoteServices节点被用来设置默认的服务地址.下面是最简单的配置:
{
"RemoteServices": {
"ProductService": {
"BaseUrl": "http://localhost:8012/",
"UseCurrentAccessToken": "true"
},
}
}
当设置 UseCurrentAccessToken 为true时说明请求是可以传送token的。那此时还要引用一个nuget包:Volo.Abp.Http.Client.IdentityModel,注意是要xxx.Host项目下引用,而不是xxx.HttpApi.Client层
并增加依赖:[DependsOn(typeof(AbpHttpClientIdentityModelModule))]
6、如何使用
可以直接在你的类中使用,就像调用本地接口一样,IBookAppService就是远程要调用的服务
public class MyService : ITransientDependency
{
private readonly IBookAppService _bookService; public MyService(IBookAppService bookService)
{
_bookService = bookService;
} public async Task DoIt()
{
var books = await _bookService.GetListAsync();
foreach (var book in books)
{
Console.WriteLine($"[BOOK {book.Id}] Name={book.Name}");
}
}
}
二、源码解析
在第一部分6节中,在使用注入接口IBookAppService时,在调用时其实是为我们生成一个代理接口去访问远程的api,也就是说当你调用接口时httpclient 拦截执并通过http形式执行你接口对应服务
我们找到和系统集成的地方,在项目HttpApi.Client 模块类中:

那我们就从这里开始源码的分析吧。此段代码是将模块中所有程序集和远程的地址传了进去,进入这个扩展方法AddHttpClientProxies,
扩展方法写在类ServiceCollectionHttpClientProxyExtensions中:

其中代码段:var serviceTypes = assembly.GetTypes().Where(IsSuitableForClientProxying).ToArray();就是从程序集中取出所有的符合要求的类,符合什么要求呢,我们再看看IsSuitableForClientProxying(ps:没想到方法在where中还可以这么调用,get了)

在这个方法中我们看到了一个非常亲切的接口IRemoteService,这就是我们自动api为什么要实现这个接口的原因了。
拿到我们所有符合要求的类后,通过foreach遍历,将符合要求的类,远程连接的地址继续往下传,调用方法AddHttpClientProxy,我们进这个方法看看做了些什么

可以看到,主要是将我们的接口,动态的去创建了一个实实,然后注入到容器中。
其中有一条经常用到的代码:typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptorType);
作用是为泛型类指定泛型类型,也就是原来是AbpAsyncDeterminationInterceptor<T>,泛型T不明确,现在明确了为 interceptorType
有一段非常重要也是核心的代码:

该方法主要是给我们的接口类Type(例如:IBookAppService ),动态的创建了一个实现类,并注入到ioc中,这样,我们在其它类中注入时,就有了该实例。
动态创建类是在第三方库中实现的,比较复杂,暂不研究,有兴趣可以参考开源:Https://github.com/castleproject/Core
ABP vNext系列文章04---DynamicClient动态代理的更多相关文章
- ABP vNext系列文章03---依赖注入
一.依赖注入的类型注册 ABP的依赖注入系统是基于Microsoft的依赖注入扩展库(Microsoft.Extensions.DependencyInjection nuget包)开发的.因此,它的 ...
- 2019 年起如何开始学习 ABP 框架系列文章-开篇有益
2019 年起如何开始学习 ABP 框架系列文章-开篇有益 [[TOC]] 本系列文章推荐阅读地址为:52ABP 开发文档 https://www.52abp.com/Wiki/52abp/lates ...
- 一步一步学习ABP项目系列文章目录
1.概述 基于DDD的.NET开发框架 - ABP初探 基于DDD的.NET开发框架 - ABP分层设计 基于DDD的.NET开发框架 - ABP模块设计 基于DDD的.NET开发框架 - ABP启动 ...
- [Abp vNext 源码分析] - 7. 权限与验证
一.简要说明 在上篇文章里面,我们在 ApplicationService 当中看到了权限检测代码,通过注入 IAuthorizationService 就可以实现权限检测.不过跳转到源码才发现,这个 ...
- Abp vNext 番外篇-疑难杂症丨浅谈扩展属性与多用户设计
说明 Abp vNext基础篇的文章还差一个单元测试模块就基本上完成了我争取10.1放假之前给大家赶稿出来,后面我们会开始进阶篇,开始拆一些东西,具体要做的事我会单独开一个文章来讲 缘起 本篇文章缘起 ...
- Android插件化原理解析——Hook机制之动态代理
转自 http://weishu.me/2016/01/28/understand-plugin-framework-proxy-hook/ 使用代理机制进行API Hook进而达到方法增强是框架的常 ...
- [Abp vNext 源码分析] - 11. 用户的自定义参数与配置
一.简要说明 文章信息: 基于的 ABP vNext 版本:1.0.0 创作日期:2019 年 10 月 23 日晚 更新日期:暂无 ABP vNext 针对用户可编辑的配置,提供了单独的 Volo. ...
- [Abp vNext 源码分析] - 12. 后台作业与后台工作者
一.简要说明 文章信息: 基于的 ABP vNext 版本:1.0.0 创作日期:2019 年 10 月 24 日晚 更新日期:暂无 ABP vNext 提供了后台工作者和后台作业的支持,基本实现与原 ...
- [Abp vNext 入坑分享] - 8.Redis与Refit的接入
前言 本章结束之后,这个abp vnext系列算是初步完结了,基础的组件都已经接入了.如果各位还需要其它的组件的话,可以自己按需要进行接入使用.其实这个只是一个基础的框架,可以自己根据需要进行变通的. ...
- jdk 动态代理的原理
一.代理设计模式 代理设计模式是Java常用的设计模式之一. 特点: 01.委托类和代理类有共同的接口或者父类: 02.代理类负责为委托类处理消息,并将消息转发给委托类: 03.委托类和代理类对象通常 ...
随机推荐
- 总结MySQL 的一些知识点:MySQL 连接的使用
MySQL 连接的使用 在前几章节中,我们已经学会了如何在一张表中读取数据,这是相对简单的,但是在真正的应用中经常需要从多个数据表中读取数据. 本章节我们将向大家介绍如何使用 MySQL 的 JOIN ...
- Solon Cloud 2.2.10 架构图发布
Solon Cloud 是在 Solon 的基础上构建的微服务开发套件.以标准与规范为核心,构建丰富的开放生态.为微服务开发提供了一个通用防腐层(即不用改代码,切换配置即可更换组件). 本次发布,展示 ...
- MySQL 数据库中的数据类型
整数类型 标准 SQL 中支持 INTEGER 和 SMALLINT 这两种类型,MySQL 数据库除了支持这两种类型以外,还扩展支持了 TINYINT.MEDIUMINT 和 BIGINT 整数类型 ...
- 【LibCurl】HomeBrew 安装 LibCurl & CMake 配置
LibCurl 在官网中明确指出支持 HomeBrew 进行安装. 那么在 macOS 端的安装就不会想 Win 下需要根据版本进行编译了,方便许多 brew install curl # 安装完成后 ...
- Redis 缓存性能实践及总结
一.前言 在互联网应用中,缓存成为高并发架构的关键组件.这篇博客主要介绍缓存使用的典型场景.实操案例分析.Redis使用规范及常规 Redis 监控. 二.常见缓存对比 常见的缓存方案,有本地缓存,包 ...
- Python 学习笔记: 从变量到装饰器
从变量开始 python 中全局变量在函数作用域内只能读,不能"写".如果要在函数作用域内实现修改全局变量值操作,需要使用关键字 global 显示指明该变量是全局变量. 但是,在 ...
- windows mysql安装及常用命令
安装windows版本mysql只是为本地代码调试,不建议用于生产.觉得步骤麻烦也可以直接下载集成环境(如xampp),一键安装即可用.之前本地测试都用一键安装,今天换个方法玩玩,安装步骤如下: my ...
- c#.net 6 实现简单爬虫几行代码实现百度搜索
使用selenium封装的简单使用工具包 Gitee:SeleniumUtil: Selenium简化工具包,包含三个主流浏览器的一些基本操作 (gitee.com) 第一步安装爬虫工具: 在程序包管 ...
- 解决python报错:ModuleNotFoundError: No module named '_sysconfigdata_x86_64_conda_linux_gnu'
技术背景 在上一篇博客中执行过conda的更新以及用conda安装了gxx_linux-64之后,再执行pip的一些指令时,就会给出如下所示的报错: $ python3 -m pip list Tra ...
- 【C/C++】 代码质量控制手段
问题引入 多人协作开发的项目,没有统一的代码规范,那么最终的编写状态必定风格迥异,产生的结果:对内,阅读审核代码是很痛苦的:对外,公司形象就是差. 单干的项目也必须要严格按照代码规范,因为最终还是会对 ...