• 聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(二)


    聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(二)

    前言

    前文排版比较糟糕,这次我们使用vscode来写本文,,各位看客请见谅。
    上文描述了 ServiceDescriptor 的三种构造形式,这决定了我们之后获取原始对象要考虑的场景,至于如何获取暂且不表,在实现细节部分我们会详细阐述。
    本文将阐述 _ProxyGenerator_的一些细节,以便各位看客更好理解 Castle 在各种场景下 如何选择合适的接口去构建代理对象(以下全称为代理对象或者 proxy

    代理对象的构建方法

    大体分成两种方式 一种是具体类 一种是根据接口生成代理对象,每种内部都会区分是否传入原始对象 看方法签名 WithTarget 即需要传入 原始对象,WithoutTarget 即不需要传入原始对象,

    • ProxyGenerator.CreateClassProxy
    • ProxyGenerator.CreateInterfaceProxy

    示例说明

    接下来我们以几种示例来介绍各个接口的使用情况

    • 假设已知 一个接口 ISampleService 和一个实现类 SampleService
    public class SampleService : ISampleService
    {
      public virtual Task  ShowAsync()
      {
        return Task.CompletedTask;
      }
    }
    
    public interface ISampleService 
    {
       Task ShowAsync();
    }
    
    public class Interceptor : IInterceptor
    {
        public  void Intercept(IInvocation invocation)
        {
            Console.WriteLine("Interceptor  starting...");
            invocation.Proceed();
            Console.WriteLine("Interceptor  ended...");
        }
    }
    

    具体类

    image

    我们想对 SampleService 进行代理生成 因为 SampleService 具有无参构造,所以我们可以这样

    var generator=new ProxyGenerator();
    var proxy = generator.CreateClassProxy(typeof(SampleService), new Interceptor());
    

    image

    假设 SampleService 有参数构造函数

    public class SampleService : ISampleService
    {
        private readonly ILogger _logger;
        public SampleService(ILogger logger)
        {
            _logger=logger;
        }
        public Task ShowAsync()
        {
            return Task.CompletedTask;
        }
    }
    ```,那么我们就可以这样
    ``` csharp
    var generator=new ProxyGenerator();
    var  sampleSvc=sp.GetRequiredService();
    var proxy = generator.CreateClassProxyWithTarget(typeof(SampleService),sampleSvc, new Interceptor());
    

    细心的朋友可能发现这时候我们引入了一个变量 而我们并未定义,
    这时候我们添加如下代码:

        var services=new ServiceCollection();
        services.AddLogging();//此处添加日志服务 伪代码 以便获取ILogger
        services.AddSingleton(sp=>new ProxyGenerator());
        servies.TryAddTransient();
        var sp=services.BuildServiceProvider();
    

    接口

    使用以上代码示例,假设我们要对 ISampleService 进行代理生成,那么我们就可以这样
    image

    services.TryAddTransient();//注入阶段添加以下代码以便获取ISampleService
    var generator=sp.GetRequiredService();
    var proxy=generator.CreateInterfaceProxyWithoutTarget(typeof(ISampleService),new Interceptor());//因为没有传入 原始对象,所以依然要求我们是一个无参构造的实现 TODO:可自行验证
    

    看下原始定义

    假设我们获取了 _ISampleService_的实例

    var  sampleSvc=sp.GetRequiredService();
    var proxy = generator.CreateInterfaceProxyWithTarget(typeof(ISampleService),sampleSvc, new Interceptor());
    

    image

    可以发现 接口代理 和具体类代理 基本相似
    细心的可以注意到 SampleService.ShowAsync 很反常的 加了个关键字 virtual,想知道为什么,这里我们借用 Castle 的文档 https://github.com/castleproject/Core/blob/master/docs/dynamicproxy-introduction.md 有兴趣的朋友可以自行查询

    总结

    说到这里,我们已经基本了解了 castle构建动态代理的基本方法,接下来我们来总结一下代理对象的构建方法。 先区分目标是类还是接口,类的代理方法要求关键字virtual,无参构造可以使用 CreateClassProxy,有参数可以先获取到原始对象,传入 CreateClassProxyWithTarget;
    接口同,无原始对象 CreateInterfaceProxyWithoutTarget ,有原始对象 CreateInterfaceProxyWithTarget
    代码太多有点枯燥,本文先到这边。

  • 相关阅读:
    Elasticsearch7从入门到精通(简介、部署、原理、开发、ELK)
    Ajax axios JSON Fastjson
    Azure SQL 数据库连接字符串
    算法--单链表
    [oeasy]python0011_ 字符序号_ordinal_ord
    如何开始破解基于 Django 的应用程序
    欧拉操作系统(openEuler)简介
    Docker 中的 .NET 异常了怎么抓 Dump
    机器学习介绍(下)
    Wireshark 用命令行分析数据包
  • 原文地址:https://www.cnblogs.com/gainorloss/p/17961414