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

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

前言

前文排版比较糟糕,这次我们使用vscode来写本文,,各位看客请见谅。

上文描述了 ServiceDescriptor 的三种构造形式,这决定了我们之后获取原始对象要考虑的场景,至于如何获取暂且不表,在实现细节部分我们会详细阐述。

本文将阐述 _ProxyGenerator_的一些细节,以便各位看客更好理解 Castle 在各种场景下 如何选择合适的接口去构建代理对象(以下全称为代理对象或者 proxy

代理对象的构建方法

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

  • ProxyGenerator.CreateClassProxy
  • ProxyGenerator.CreateInterfaceProxy

示例说明

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

  • 假设已知 一个接口 ISampleService 和一个实现类 SampleService
csharp 复制代码
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...");
    }
}

具体类

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

csharp 复制代码
var generator=new ProxyGenerator();
var proxy = generator.CreateClassProxy(typeof(SampleService), new Interceptor());

假设 SampleService 有参数构造函数

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

细心的朋友可能发现这时候我们引入了一个变量 而我们并未定义,

这时候我们添加如下代码:

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

接口

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

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

看下原始定义

假设我们获取了 _ISampleService_的实例

csharp 复制代码
var  sampleSvc=sp.GetRequiredService<ISampleService>();
var proxy = generator.CreateInterfaceProxyWithTarget(typeof(ISampleService),sampleSvc, new Interceptor());

可以发现 接口代理 和具体类代理 基本相似

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

总结

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

接口同,无原始对象 CreateInterfaceProxyWithoutTarget ,有原始对象 CreateInterfaceProxyWithTarget

代码太多有点枯燥,本文先到这边。

相关推荐
滴滴答答哒8 小时前
.NET Core 基于 AOP + Polly 实现数据库死锁自动重试
数据库·.netcore·sqlsugar
.NET修仙日记3 天前
.NET EFCore批量插入性能优化实战:30秒 → 0.5秒
性能优化·c#·.net·.netcore·微软技术·efcore·踩坑实录
Kimhill张7 天前
.net core8 WPF 依赖注入(DI)
wpf·.netcore
wangl_928 天前
C# / .NET 在工业环境中的优势
开发语言·c#·.net·.netcore·.net core·visual studio
豆豆10 天前
信创环境下CMS国产化适配实践:以.NET Core路线为例的技术验证
.netcore·cms·信创·国产化·建站系统·内容管理系统·网站管理系统
时光追逐者11 天前
C#/.NET/.NET Core技术前沿周刊 | 第 70 期(2026年5.01-5.10)
c#·.net·.netcore
van久15 天前
Day20:AutoMapper 对象映射
.netcore
van久16 天前
Day23 登录 + 颁发 Token(DDD 四层架构 + 企业标准)
.netcore
wangl_9217 天前
C#性能优化完全指南 - 从原理到实践
开发语言·性能优化·c#·.net·.netcore·visual studio
宝桥南山20 天前
GitHub Models - 尝试一下使用GitHub Models
microsoft·ai·微软·c#·github·.netcore