当前位置:首页 > C# > 正文

C#依赖注入中的装饰器嵌套(深入理解.NET Core中服务装饰器的链式调用)

在现代 C# 开发中,尤其是使用 .NET Core 或 .NET 5+ 构建应用程序时,依赖注入(Dependency Injection, DI)已成为标准实践。而装饰器模式(Decorator Pattern)则是一种强大的设计模式,用于在不修改原始类的前提下动态地为对象添加行为。当我们将两者结合——即通过依赖注入容器实现服务装饰器的嵌套(或称链式装饰)——就能构建出高度可扩展、可维护且松耦合的系统。

本文将手把手教你如何在 C# 中利用 .NET 的内置依赖注入容器实现装饰器嵌套,即使你是编程新手也能轻松上手!

C#依赖注入中的装饰器嵌套(深入理解.NET Core中服务装饰器的链式调用) C#依赖注入 装饰器模式 .NET Core依赖注入 服务装饰器嵌套 第1张

什么是装饰器模式?

装饰器模式允许你通过将对象放入包含行为的特殊包装器(即“装饰器”)中来为对象添加新功能。这些装饰器与被装饰的对象实现相同的接口,因此可以透明地替换原始对象。

为什么要在依赖注入中使用装饰器?

在实际项目中,我们常常需要为某个服务添加日志记录、缓存、权限验证、性能监控等功能。如果把这些逻辑硬编码到服务类中,会导致代码臃肿、难以测试和复用。而通过依赖注入注册多个装饰器,我们可以像搭积木一样灵活组合功能。

实战:实现一个嵌套装饰器链

假设我们要实现一个简单的消息发送服务 IMessageService,并为其添加日志和性能计时两个装饰器。

第 1 步:定义服务接口

public interface IMessageService{    string SendMessage(string message);}

第 2 步:实现基础服务

public class EmailMessageService : IMessageService{    public string SendMessage(string message)    {        // 模拟发送邮件        return $"[Email] Sent: {message}";    }}

第 3 步:创建第一个装饰器 —— 日志装饰器

public class LoggingDecorator : IMessageService{    private readonly IMessageService _innerService;    private readonly ILogger<LoggingDecorator> _logger;    public LoggingDecorator(IMessageService innerService, ILogger<LoggingDecorator> logger)    {        _innerService = innerService;        _logger = logger;    }    public string SendMessage(string message)    {        _logger.LogInformation($"Sending message: {message}");        var result = _innerService.SendMessage(message);        _logger.LogInformation($"Message sent successfully: {result}");        return result;    }}

第 4 步:创建第二个装饰器 —— 性能计时装饰器

public class TimingDecorator : IMessageService{    private readonly IMessageService _innerService;    private readonly ILogger<TimingDecorator> _logger;    public TimingDecorator(IMessageService innerService, ILogger<TimingDecorator> logger)    {        _innerService = innerService;        _logger = logger;    }    public string SendMessage(string message)    {        var stopwatch = System.Diagnostics.Stopwatch.StartNew();        var result = _innerService.SendMessage(message);        stopwatch.Stop();        _logger.LogInformation($"SendMessage took {stopwatch.ElapsedMilliseconds} ms");        return result;    }}

第 5 步:在 Program.cs 中注册嵌套装饰器

.NET 的内置 DI 容器不直接支持自动装饰器注册,但我们可以通过工厂委托手动构建嵌套链:

// Program.cs (.NET 6+ Minimal API 风格)var builder = WebApplication.CreateBuilder(args);// 注册基础服务builder.Services.AddSingleton<IMessageService, EmailMessageService>();// 手动构建装饰器链:Timing -> Logging -> Emailbuilder.Services.Decorate<IMessageService>((serviceProvider, inner) =>    new TimingDecorator(        new LoggingDecorator(inner, serviceProvider.GetRequiredService<ILogger<LoggingDecorator>>()),        serviceProvider.GetRequiredService<ILogger<TimingDecorator>>()    ));// 注意:上面的 Decorate 是自定义扩展方法(见下文)

为了简化注册,我们可以创建一个通用的 Decorate 扩展方法:

public static class ServiceCollectionExtensions{    public static void Decorate<TService>(this IServiceCollection services,        Func<IServiceProvider, TService, TService> decoratorFactory)        where TService : class    {        var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(TService));        if (descriptor == null)            throw new InvalidOperationException($"{typeof(TService)} is not registered.");        services.Remove(descriptor);        services.Add(new ServiceDescriptor(            typeof(TService),            provider => decoratorFactory(provider, (TService)provider.GetService(descriptor.ImplementationType)!),            descriptor.Lifetime        ));    }}

运行效果

当你注入 IMessageService 并调用 SendMessage 时,执行顺序将是:

  1. TimingDecorator 开始计时
  2. LoggingDecorator 记录日志
  3. EmailMessageService 执行实际发送
  4. LoggingDecorator 记录成功日志
  5. TimingDecorator 输出耗时

SEO关键词回顾

本文深入讲解了如何在 C# 项目中实现 C#依赖注入装饰器模式 的结合,并展示了 .NET Core依赖注入 容器中 服务装饰器嵌套 的完整流程。这些技术是构建企业级应用的核心技能。

小结

通过依赖注入实现装饰器嵌套,不仅能提升代码的可读性和可维护性,还能让你的服务具备“插件式”扩展能力。虽然 .NET 内置 DI 不原生支持自动装饰,但借助简单的扩展方法,我们完全可以优雅地实现这一模式。

现在,你已经掌握了 C# 中依赖注入装饰器嵌套的核心技巧!快去你的项目中试试吧!