.net core 动态代理

warning: 这篇文章距离上次修改已过516天,其中的内容可能已经有所变动。

动态代理简介

对于某一个实例,对其行为进行无感知的包装。从而达到AOP的目的。

目前想到一个比较典型的例子就是向外部发送请求,对接第三方接口时,大多数都是如下情况:

  1. 像外部指定接口发送请求
  2. 接收返回数据
  3. 处理异常
  4. 处理返回数据
  5. 返回给业务系统

这中间其实是一个很通用的操作,非常标准化的流程。但是很多情况下都要重复的去实现,因此想将这部分做一个代理,并且是一种完全依赖接口的代理(无需实现接口)。

示例(设想)

在实现前,我们先来假设一下最终使用时的效果,这只是一个粗糙的想法,后面来慢慢完善。

定义:

[Proxy(typeof(HttpRequestProxy))]
[RequestHost("https://example.com/api")]
public interface OtherSystem
{
    [HttpGet]
    [Route("userinfo")]
    UserInfoResponse GetUserInfo(long id);
}

使用(基于IOC):

public class UserService
{
    private readonly OtherSystem otherSystem;

    public UserService(OtherSystem otherSystem)
    {
        this.otherSystem = otherSystem;
    }

    public UserInfo GetUserInfo(long id)
    {
        return this.otherSystem.GetUserInfo(id);
    }
}

这其中还可以直接使用原生中已有的Attribute,避免重复造轮子,也可以语义化,并且利用现有特性来完成功能。

技术分析

目前代理实现分为几种:

  1. 原生DispatchProxy
  2. 第三方Castle DynamicProxy
  3. Feign(Java, spring cloud openFeign),声明式客户端

DispatchProxy

官方文档

基于DispatchProxy可以实现核心的几个功能:

  1. 解析interface的注解,获取请求信息。
  2. 解析method的注解,获取具体请求路径,参数,返回值类型等。
  3. 拦截调用,不调用具体实例。

HttpClient

httpClient本身支持多配置,并且能通过HttpClientFactory进行实例化,相当于自带管理了。

services.AddHttpClient("wechat", c => 
{
    c.BaseAddress = new Uri("https://example.com/api")
})

实例化:

public class TestService
{
    private readonly IHttpClientFactory httpClientFactory;

    public TestService(IHttpClientFactory httpClientFactory)
    {
        this.httpClientFactory = httpClientFactory;
    }

    public void test()
    {
        var client = httpClientFactory.CreateClient("wechat");
    }
}

实现

在实现之前先指定一下规则,确定下来使用。

注解

  • RemoteClient(string name),用于接口上,扫描到此类会被自动注册并代理
  • HttpMethodBase,用于方法上,这里沿用Mvc中的标签,支持路由模板
  • RequestRoute(string name),用于指定参数去向,下同
  • ReqeustQuery(string name)
  • RequestBody(string name)
  • RequestHeader(string name)
  • RequestForm(string name)

HttpDispatchProxy<Targettype>

none
最后修改于:2022年12月20日 22:47

评论已关闭