实用指南:深入解析.NET MediatR事件机制:从基础到DDD实战

在.NET开发中,模块间的耦合问题一直是架构设计的痛点。MediatR作为轻量级的中介者模式实现库,凭借其简洁的API和强大的解耦能力,成为了.NET生态中实现发布/订阅、领域事件的首选工具。其中事件(Notification)机制更是MediatR的核心亮点——它让我们能优雅地处理“一个动作触发多个响应”的场景,比如用户注册后发送邮件、记录日志、同步数据等。

本文将从基础概念到实战落地,结合真实项目案例,全面拆解MediatR事件机制,带你吃透这一利器!

一、MediatR事件的核心:发布-订阅模式

MediatR的事件机制本质是发布-订阅模式的实现,核心逻辑是:发布者只负责发布事件,不关心谁处理;订阅者只负责处理事件,不关心谁发布。这种“解耦”特性让代码更易维护和扩展。

核心组件关系图

核心组件关系图

关键组件速览

组件接口作用
INotification事件标记接口,定义事件类型(仅标记,无方法)
INotificationHandler<T>事件处理器接口(同步/异步),T为具体事件类型
IMediator中介者核心接口,提供Publish方法发布事件
IPipelineBehavior事件管道行为,用于全局拦截(日志、验证、异常处理等)

二、快速上手:5分钟实现一个事件流程

我们以“用户注册后触发多任务”为例,从零实现MediatR事件。

1. 环境准备

安装必要NuGet包:

# 核心包
Install-Package MediatR
# ASP.NET Core依赖注入扩展
Install-Package MediatR.Extensions.Microsoft.DependencyInjection

2. 定义事件(INotification)

事件本质是“数据载体”,需实现INotification接口:

/// 
/// 用户注册事件(事件数据)
/// 
public class UserRegisteredEvent : INotification
{
    public Guid UserId { get; init; } // 不可变,保证事件数据安全
    public string Username { get; init; }
    public string Email { get; init; }
    public DateTime RegisteredTime { get; init; } = DateTime.UtcNow;
}

3. 编写事件处理器(多处理器支持)

一个事件可绑定多个处理器,每个处理器负责单一职责:

/// 
/// 处理器1:发送欢迎邮件
/// 
public class SendWelcomeEmailHandler : IAsyncNotificationHandler
{
    private readonly IEmailService _emailService;
    public SendWelcomeEmailHandler(IEmailService emailService)
    {
        _emailService = emailService;
    }
    public async Task Handle(UserRegisteredEvent notification, CancellationToken cancellationToken)
    {
        await _emailService.SendAsync(
            to: notification.Email,
            subject: "欢迎加入我们!",
            content: $"尊敬的{notification.Username},恭喜您注册成功!",
            cancellationToken: cancellationToken);
        Console.WriteLine($"向{notification.Email}发送欢迎邮件!");
    }
}
/// 
/// 处理器2:记录注册日志
/// 
public class LogUserRegisterHandler : INotificationHandler
{
    private readonly ILogger _logger;
    public LogUserRegisterHandler(ILogger logger)
    {
        _logger = logger;
    }
    public void Handle(UserRegisteredEvent notification, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"用户{notification.Username}(ID:{notification.UserId})注册成功,时间:{notification.RegisteredTime}");
    }
}
/// 
/// 处理器3:初始化用户默认角色
/// 
public class InitUserRoleHandler : IAsyncNotificationHandler
{
    private readonly IUserRoleService _userRoleService;
    public InitUserRoleHandler(IUserRoleService userRoleService)
    {
        _userRoleService = userRoleService;
    }
    public async Task Handle(UserRegisteredEvent notification, CancellationToken cancellationToken)
    {
        await _userRoleService.AssignDefaultRoleAsync(notification.UserId, cancellationToken);
        Console.WriteLine($"为用户{notification.UserId}分配默认角色!");
    }
}

4. 注册MediatR服务

Program.cs中注册MediatR(扫描当前程序集的事件/处理器):

var builder = WebApplication.CreateBuilder(args);
// 注册MediatR
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
// 注册业务服务
builder.Services.AddScoped();
builder.Services.AddScoped();

5. 发布事件

在业务逻辑中通过IMediator发布事件:

[ApiController]
[Route("users")]
public class UserController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly IUserRepository _userRepository;
    public UserController(IMediator mediator, IUserRepository userRepository)
    {
        _mediator = mediator;
        _userRepository = userRepository;
    }
    [HttpPost("register")]
    public async Task Register([FromBody] RegisterRequest request, CancellationToken cancellationToken)
    {
        // 1. 业务逻辑:创建用户
        var user = new User
        {
            Id = Guid.NewGuid(),
            Username = request.Username,
            Email = request.Email,
            PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password)
        };
        await _userRepository.AddAsync(user, cancellationToken);
        // 2. 发布用户注册事件
        await _mediator.Publish(new UserRegisteredEvent
        {
            UserId = user.Id,
            Username = user.Username,
            Email = user.Email
        }, cancellationToken);
        return Ok(new { UserId = user.Id, Message = "注册成功" });
    }
}

运行效果

调用接口后,控制台会输出:

用户张三(ID:xxx-xxx-xxx)注册成功,时间:2025-11-28 15:30:00
向zhangsan@example.com发送欢迎邮件!
为用户xxx-xxx-xxx分配默认角色!

一个事件触发了三个独立的处理器,且发布者完全不感知处理器的存在——这就是解耦的魅力!

三、高级特性:让事件机制更强大

1. 管道行为:全局拦截事件流程

通过IPipelineBehavior,我们可以在事件处理的“前置/后置”插入通用逻辑(如日志、验证),实现AOP思想。

示例:事件日志管道
/// 
/// 全局事件日志管道
/// 
public class NotificationLoggingBehavior : IPipelineBehavior
    where TNotification : INotification
{
    private readonly ILogger> _logger;
    public NotificationLoggingBehavior(ILogger> logger)
    {
        _logger = logger;
    }
    public async Task Handle(TNotification notification, RequestHandlerDelegate next, CancellationToken cancellationToken)
    {
        // 事件处理前:记录日志
        var eventType = notification.GetType().Name;
        _logger.LogInformation($"开始处理事件:{eventType},数据:{JsonSerializer.Serialize(notification)}");
        try
        {
            // 执行后续处理器
            await next();
            _logger.LogInformation($"事件{eventType}处理完成");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"事件{eventType}处理失败");
            throw;
        }
        return Unit.Value;
    }
}

注册管道(DI中添加):

builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(NotificationLoggingBehavior<>));

2. 泛型处理器:处理一类事件

如果有多个事件需要统一处理(如所有领域事件记录日志),可以用泛型处理器

/// 
/// 领域事件基类
/// 
public abstract class BaseDomainEvent : INotification
{
    public Guid EventId { get; } = Guid.NewGuid();
    public DateTime OccurredOn { get; } = DateTime.UtcNow;
    public string AggregateId { get; init; } // 聚合根ID
}
/// 
/// 泛型处理器:处理所有领域事件
/// 
public class DomainEventLogger : INotificationHandler
    where TEvent : BaseDomainEvent
{
    private readonly ILogger> _logger;
    public DomainEventLogger(ILogger> logger) => _logger = logger;
    public Task Handle(TEvent notification, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"领域事件[{typeof(TEvent).Name}]:ID={notification.EventId},聚合根ID={notification.AggregateId},发生时间={notification.OccurredOn}");
        return Task.CompletedTask;
    }
}

四、实战DDD:领域事件的落地

在DDD(领域驱动设计)中,领域事件是捕获领域内状态变化的关键。MediatR是实现领域事件的最佳搭档,我们来看完整的集成流程。

领域事件生命周期流程图

领域事件生命周期流程图

1. 实体中存储领域事件

/// 
/// 聚合根基类(包含领域事件)
/// 
public abstract class AggregateRoot
{
    private readonly List _domainEvents = new();
    public IReadOnlyCollection DomainEvents => _domainEvents.AsReadOnly();
    protected void AddDomainEvent(INotification eventItem) => _domainEvents.Add(eventItem);
    public void ClearDomainEvents() => _domainEvents.Clear();
}
/// 
/// 订单聚合根
/// 
public class Order : AggregateRoot
{
    public Guid Id { get; private set; }
    public decimal Amount { get; private set; }
    public OrderStatus Status { get; private set; }
    public Guid CustomerId { get; private set; }
    /// 
    /// 创建订单(工厂方法)
    /// 
    public static Order Create(Guid customerId, decimal amount, List items)
    {
        if (amount <= 0) throw new ArgumentException("订单金额必须大于0");
        if (!items.Any()) throw new ArgumentException("订单商品不能为空");
        var order = new Order
        {
            Id = Guid.NewGuid(),
            CustomerId = customerId,
            Amount = amount,
            Status = OrderStatus.Created,
        };
        // 添加领域事件:订单创建事件
        order.AddDomainEvent(new OrderCreatedEvent
        {
            AggregateId = order.Id.ToString(),
            OrderId = order.Id,
            CustomerId = customerId,
            Amount = amount,
            ItemCount = items.Count
        });
        return order;
    }
    /// 
    /// 支付订单
    /// 
    public void Pay(DateTime paidTime)
    {
        if (Status != OrderStatus.Created) throw new InvalidOperationException("只有待支付订单可支付");
        Status = OrderStatus.Paid;
        // 添加领域事件:订单支付事件
        AddDomainEvent(new OrderPaidEvent
        {
            AggregateId = Id.ToString(),
            OrderId = Id,
            PaidTime = paidTime
        });
    }
}
/// 
/// 订单创建事件
/// 
public class OrderCreatedEvent : BaseDomainEvent
{
    public Guid OrderId { get; init; }
    public Guid CustomerId { get; init; }
    public decimal Amount { get; init; }
    public int ItemCount { get; init; }
}
/// 
/// 订单支付事件
/// 
public class OrderPaidEvent : BaseDomainEvent
{
    public Guid OrderId { get; init; }
    public DateTime PaidTime { get; init; }
}

2. 仓储中发布领域事件

public class OrderRepository : IOrderRepository
{
    private readonly AppDbContext _dbContext;
    private readonly IMediator _mediator;
    public OrderRepository(AppDbContext dbContext, IMediator mediator)
    {
        _dbContext = dbContext;
        _mediator = mediator;
    }
    public async Task AddAsync(Order order, CancellationToken cancellationToken)
    {
        await _dbContext.Orders.AddAsync(order, cancellationToken);
        await _dbContext.SaveChangesAsync(cancellationToken);
        // 发布所有领域事件
        foreach (var domainEvent in order.DomainEvents)
        {
            await _mediator.Publish(domainEvent, cancellationToken);
        }
        // 清空事件,避免重复发布
        order.ClearDomainEvents();
    }
    public async Task UpdateAsync(Order order, CancellationToken cancellationToken)
    {
        _dbContext.Orders.Update(order);
        await _dbContext.SaveChangesAsync(cancellationToken);
        // 发布领域事件
        foreach (var domainEvent in order.DomainEvents)
        {
            await _mediator.Publish(domainEvent, cancellationToken);
        }
        order.ClearDomainEvents();
    }
}

五、实际项目中的经典案例

案例1:电商订单创建后的连锁操作

场景:用户下单后,需要扣减商品库存、生成物流单、发送订单确认短信、添加积分。

事件定义
public class OrderCreatedEvent : BaseDomainEvent
{
    public Guid OrderId { get; init; }
    public List Items { get; init; } = new();
    public Guid CustomerId { get; init; }
    public decimal TotalAmount { get; init; }
}
处理器实现
/// 
/// 处理器1:扣减商品库存
/// 
public class DeductStockHandler : IAsyncNotificationHandler
{
    private readonly IStockService _stockService;
    public DeductStockHandler(IStockService stockService) => _stockService = stockService;
    public async Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
    {
        foreach (var item in notification.Items)
        {
            await _stockService.DeductAsync(item.ProductId, item.Quantity, cancellationToken);
        }
        Console.WriteLine($"订单{notification.OrderId}库存扣减完成!");
    }
}
/// 
/// 处理器2:生成物流单
/// 
public class CreateLogisticsHandler : IAsyncNotificationHandler
{
    private readonly ILogisticsService _logisticsService;
    public CreateLogisticsHandler(ILogisticsService logisticsService) => _logisticsService = logisticsService;
    public async Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
    {
        var logistics = await _logisticsService.CreateAsync(
            orderId: notification.OrderId,
            customerId: notification.CustomerId,
            cancellationToken: cancellationToken);
        Console.WriteLine($"订单{notification.OrderId}物流单生成:{logistics.LogisticsNo}");
    }
}
/// 
/// 处理器3:发送订单确认短信
/// 
public class SendOrderSmsHandler : IAsyncNotificationHandler
{
    private readonly ISmsService _smsService;
    private readonly ICustomerRepository _customerRepository;
    public SendOrderSmsHandler(ISmsService smsService, ICustomerRepository customerRepository)
    {
        _smsService = smsService;
        _customerRepository = customerRepository;
    }
    public async Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
    {
        var customer = await _customerRepository.GetByIdAsync(notification.CustomerId, cancellationToken);
        await _smsService.SendAsync(
            phone: customer.Phone,
            content: $"您的订单{notification.OrderId}已创建,金额{notification.TotalAmount}元,我们将尽快发货!",
            cancellationToken: cancellationToken);
        Console.WriteLine($"向{customer.Phone}发送订单确认短信!");
    }
}
/// 
/// 处理器4:添加用户积分
/// 
public class AddCustomerPointsHandler : IAsyncNotificationHandler
{
    private readonly ICustomerService _customerService;
    public AddCustomerPointsHandler(ICustomerService customerService) => _customerService = customerService;
    public async Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
    {
        var points = (int)notification.TotalAmount; // 1元=1积分
        await _customerService.AddPointsAsync(notification.CustomerId, points, cancellationToken);
        Console.WriteLine($"为用户{notification.CustomerId}添加{points}积分!");
    }
}

案例2:用户修改密码后的安全处理

场景:用户修改密码后,需要强制登出所有设备、记录安全日志、发送密码修改提醒邮件。

事件定义
public class PasswordChangedEvent : INotification
{
    public Guid UserId { get; init; }
    public string Email { get; init; }
    public DateTime ChangedTime { get; init; } = DateTime.UtcNow;
    public string IpAddress { get; init; } // 修改密码的IP地址
}
处理器实现
/// 
/// 处理器1:强制登出所有设备
/// 
public class LogoutAllDevicesHandler : IAsyncNotificationHandler
{
    private readonly ITokenService _tokenService;
    public LogoutAllDevicesHandler(ITokenService tokenService) => _tokenService = tokenService;
    public async Task Handle(PasswordChangedEvent notification, CancellationToken cancellationToken)
    {
        await _tokenService.RevokeAllTokensAsync(notification.UserId, cancellationToken);
        Console.WriteLine($"用户{notification.UserId}所有设备已登出!");
    }
}
/// 
/// 处理器2:记录安全日志
/// 
public class LogPasswordChangeHandler : INotificationHandler
{
    private readonly ISecurityLogService _logService;
    public LogPasswordChangeHandler(ISecurityLogService logService) => _logService = logService;
    public void Handle(PasswordChangedEvent notification, CancellationToken cancellationToken)
    {
        _logService.AddLog(new SecurityLog
        {
            UserId = notification.UserId,
            Operation = "PasswordChanged",
            IpAddress = notification.IpAddress,
            OperationTime = notification.ChangedTime
        });
        Console.WriteLine($"记录用户{notification.UserId}密码修改日志(IP:{notification.IpAddress})!");
    }
}
/// 
/// 处理器3:发送密码修改提醒邮件
/// 
public class SendPasswordChangeEmailHandler : IAsyncNotificationHandler
{
    private readonly IEmailService _emailService;
    public SendPasswordChangeEmailHandler(IEmailService emailService) => _emailService = emailService;
    public async Task Handle(PasswordChangedEvent notification, CancellationToken cancellationToken)
    {
        await _emailService.SendAsync(
            to: notification.Email,
            subject: "您的密码已修改",
            content: $"您的账号于{notification.ChangedTime:yyyy-MM-dd HH:mm:ss}修改了密码,若非本人操作请及时联系客服!",
            cancellationToken: cancellationToken);
        Console.WriteLine($"向{notification.Email}发送密码修改提醒邮件!");
    }
}

案例3:文章发布后的SEO处理

场景:文章发布后,需要生成搜索引擎索引、推送链接到百度/谷歌、更新站点地图、通知订阅用户。

事件定义
public class ArticlePublishedEvent : BaseDomainEvent
{
    public Guid ArticleId { get; init; }
    public string Title { get; init; }
    public string Slug { get; init; } // SEO友好URL
    public string Content { get; init; }
    public Guid AuthorId { get; init; }
    public DateTime PublishedTime { get; init; } = DateTime.UtcNow;
}
处理器实现
/// 
/// 处理器1:生成搜索引擎索引
/// 
public class BuildSearchIndexHandler : IAsyncNotificationHandler
{
    private readonly ISearchIndexService _searchIndexService;
    public BuildSearchIndexHandler(ISearchIndexService searchIndexService) => _searchIndexService = searchIndexService;
    public async Task Handle(ArticlePublishedEvent notification, CancellationToken cancellationToken)
    {
        await _searchIndexService.AddIndexAsync(new SearchIndex
        {
            Id = notification.ArticleId,
            Title = notification.Title,
            Content = notification.Content,
            Type = "Article"
        }, cancellationToken);
        Console.WriteLine($"文章{notification.ArticleId}搜索索引生成完成!");
    }
}
/// 
/// 处理器2:推送链接到搜索引擎
/// 
public class PushToSearchEngineHandler : IAsyncNotificationHandler
{
    private readonly ISearchEngineService _searchEngineService;
    public PushToSearchEngineHandler(ISearchEngineService searchEngineService) => _searchEngineService = searchEngineService;
    public async Task Handle(ArticlePublishedEvent notification, CancellationToken cancellationToken)
    {
        var articleUrl = $"https://example.com/articles/{notification.Slug}";
        await _searchEngineService.PushToBaiduAsync(articleUrl, cancellationToken);
        await _searchEngineService.PushToGoogleAsync(articleUrl, cancellationToken);
        Console.WriteLine($"文章链接{articleUrl}已推送到百度/谷歌!");
    }
}
/// 
/// 处理器3:更新站点地图
/// 
public class UpdateSitemapHandler : INotificationHandler
{
    private readonly ISitemapService _sitemapService;
    public UpdateSitemapHandler(ISitemapService sitemapService) => _sitemapService = sitemapService;
    public void Handle(ArticlePublishedEvent notification, CancellationToken cancellationToken)
    {
        _sitemapService.AddUrl(
            url: $"https://example.com/articles/{notification.Slug}",
            lastModified: notification.PublishedTime,
            changeFrequency: "weekly",
            priority: 0.8);
        Console.WriteLine($"站点地图已更新,添加文章{notification.Title}!");
    }
}
/// 
/// 处理器4:通知订阅用户
/// 
public class NotifySubscribersHandler : IAsyncNotificationHandler
{
    private readonly ISubscriptionService _subscriptionService;
    private readonly IEmailService _emailService;
    public NotifySubscribersHandler(ISubscriptionService subscriptionService, IEmailService emailService)
    {
        _subscriptionService = subscriptionService;
        _emailService = emailService;
    }
    public async Task Handle(ArticlePublishedEvent notification, CancellationToken cancellationToken)
    {
        var subscribers = await _subscriptionService.GetArticleSubscribersAsync(notification.AuthorId, cancellationToken);
        foreach (var subscriber in subscribers)
        {
            await _emailService.SendAsync(
                to: subscriber.Email,
                subject: $"新文章发布:{notification.Title}",
                content: $"您关注的作者发布了新文章《{notification.Title}》,点击查看:https://example.com/articles/{notification.Slug}",
                cancellationToken: cancellationToken);
        }
        Console.WriteLine($" 已通知{subscribers.Count}位订阅用户新文章发布!");
    }
}

六、最佳实践:避坑指南

1. 事件命名规范

  • 过去式命名(如UserRegisteredEventOrderPaidEvent),体现事件“已发生”;

  • 前缀+动作(如OrderCreatedEventProductStockChangedEvent),一眼看懂业务含义。

2. 处理器单一职责

每个处理器只做一件事(如“发邮件”和“记日志”拆分为两个处理器),避免臃肿。

3. 避免耗时操作

事件处理器默认同步阻塞,耗时操作(如调用第三方API)应改用后台任务(如IHostedService、Hangfire):

/// 
/// 耗时操作处理器(使用后台任务)
/// 
public class SyncToThirdPartyHandler : IAsyncNotificationHandler
{
    private readonly IBackgroundTaskQueue _taskQueue;
    public SyncToThirdPartyHandler(IBackgroundTaskQueue taskQueue) => _taskQueue = taskQueue;
    public Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
    {
        // 将耗时操作加入后台队列
        _taskQueue.QueueBackgroundWorkItem(async token =>
        {
            // 模拟耗时操作
            await Task.Delay(5000, token);
            Console.WriteLine($"订单{notification.OrderId}已同步到第三方系统!");
        });
        return Task.CompletedTask;
    }
}

4. 事件数据不可变

事件发布后数据不应被修改,建议用init或只读字段(如public Guid UserId { get; init; })。

5. 异常隔离

单个处理器异常不应影响其他处理器,可在管道行为中捕获异常并记录,而非抛出:

// 改进的管道行为:隔离处理器异常
public async Task Handle(TNotification notification, RequestHandlerDelegate next, CancellationToken cancellationToken)
{
    var eventType = notification.GetType().Name;
    _logger.LogInformation($" 开始处理事件:{eventType}");
    try
    {
        await next();
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, $"❌ 事件{eventType}部分处理器执行失败");
        // 不抛出异常,避免影响其他处理器
    }
    _logger.LogInformation($"✅ 事件{eventType}处理完成(部分处理器可能失败)");
    return Unit.Value;
}

七、常见问题解答

Q1:事件处理器不执行怎么办?

  • 检查MediatR是否注册了处理器所在的程序集;

  • 确认处理器实现的是INotificationHandler<T>(而非IRequestHandler<T>);

  • 事件类型与处理器泛型参数是否匹配(如UserRegisteredEvent对应INotificationHandler<UserRegisteredEvent>)。

Q2:如何让处理器按顺序执行?

MediatR默认并行执行多处理器,若需顺序执行,可自定义管道行为控制执行顺序:

// 顺序执行处理器的管道行为
public class SequentialExecutionBehavior : IPipelineBehavior
    where TNotification : INotification
{
    private readonly IEnumerable> _handlers;
    public SequentialExecutionBehavior(IEnumerable> handlers)
    {
        _handlers = handlers;
    }
    public async Task Handle(TNotification notification, RequestHandlerDelegate next, CancellationToken cancellationToken)
    {
        foreach (var handler in _handlers)
        {
            await handler.Handle(notification, cancellationToken);
        }
        return Unit.Value;
    }
}

Q3:跨服务事件怎么处理?

MediatR仅支持进程内事件,跨服务需结合消息队列(如RabbitMQ、Kafka):

/// 
/// 跨服务事件处理器(发布到RabbitMQ)
/// 
public class PublishToRabbitMQHandler : IAsyncNotificationHandler
{
    private readonly IMessagePublisher _messagePublisher;
    public PublishToRabbitMQHandler(IMessagePublisher messagePublisher) => _messagePublisher = messagePublisher;
    public async Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
    {
        await _messagePublisher.PublishAsync(
            exchange: "order.events",
            routingKey: "order.created",
            message: notification,
            cancellationToken: cancellationToken);
        Console.WriteLine($" 订单创建事件已发布到RabbitMQ!");
    }
}

总结:MediatR事件的价值

MediatR事件机制的核心价值在于解耦——它让“发布者”和“订阅者”彻底分离,让代码从“硬编码调用”走向“事件驱动”。无论是电商订单的连锁操作、用户安全的多维度处理,还是内容发布的SEO联动,MediatR都能让复杂的业务逻辑变得清晰、可扩展。

掌握它,你将告别模块间的“紧耦合噩梦”,写出更干净、更易维护的.NET代码!

附录

10年.NET开发者,多年收集整理的.NET学习知识库,现免费分享给各位开发者朋友 .NET知识库,涵盖了.NET Web开发、桌面开发、微服务等视频教程,必读书籍推荐,教程源码,面试题库等全面学习资料

最后:如果觉得本文有用,欢迎点赞收藏~ 关注我,后续分享更多.NET架构实战技巧!

posted @ 2025-12-24 19:37  gccbuaa  阅读(17)  评论(0)    收藏  举报