在现代软件开发中,解耦是构建可维护、可扩展系统的关键。事件驱动架构(Event-Driven Architecture,简称 EDA)为我们提供了一种强大的解耦方案,允许组件之间通过事件进行松散耦合的通信。本文将深入探讨如何在 C# 中利用事件驱动架构实现应用解耦。
事件驱动架构基于以下关键概念:
我们将通过一个电子商务订单系统的例子,展示事件驱动架构的实际应用。
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppEvent
{
public class Order
{
public string Id { get; set; }
public string CustomerId { get; set; }
public decimal TotalAmount { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
// 可以根据需要添加其他属性,例如订单状态、商品列表等
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppEvent
{
// 事件基接口
public interface IEvent
{
Guid EventId { get; }
DateTime Timestamp { get; }
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppEvent
{
// 订单创建事件
public class OrderCreatedEvent : IEvent
{
public Guid EventId { get; } = Guid.NewGuid();
public DateTime Timestamp { get; } = DateTime.UtcNow;
public string OrderId { get; set; }
public decimal TotalAmount { get; set; }
public string CustomerEmail { get; set; }
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppEvent
{
public class EventBus
{
// 使用委托和字典实现事件订阅机制
private readonly Dictionary<Type, List<Delegate>> _handlers = new();
// 订阅事件
public void Subscribe<T>(Action<T> handler) where T : IEvent
{
var eventType = typeof(T);
if (!_handlers.ContainsKey(eventType))
{
_handlers[eventType] = new List<Delegate>();
}
_handlers[eventType].Add(handler);
}
// 发布事件
public void Publish<T>(T eventToPublish) where T : IEvent
{
var eventType = typeof(T);
if (_handlers.ContainsKey(eventType))
{
foreach (var handler in _handlers[eventType])
{
((Action<T>)handler)(eventToPublish);
}
}
}
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppEvent
{
public class OrderService
{
private readonly EventBus _eventBus;
public OrderService(EventBus eventBus)
{
_eventBus = eventBus;
}
// 创建订单方法
public void CreateOrder(string customerId, decimal totalAmount)
{
// 订单创建逻辑
var order = new Order
{
Id = Guid.NewGuid().ToString(),
CustomerId = customerId,
TotalAmount = totalAmount
};
// 发布订单创建事件
var orderCreatedEvent = new OrderCreatedEvent
{
OrderId = order.Id,
TotalAmount = totalAmount,
CustomerEmail = GetCustomerEmail(customerId)
};
_eventBus.Publish(orderCreatedEvent);
}
// 获取客户邮箱的方法
private string GetCustomerEmail(string customerId)
{
// 这里可以根据 customerId 从数据库或其他数据源获取客户邮箱
// 示例返回一个假邮箱
return $"{customerId}@example.com";
}
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AppEvent
{
public class NotificationService
{
public NotificationService(EventBus eventBus)
{
// 订阅订单创建事件
eventBus.Subscribe<OrderCreatedEvent>(HandleOrderCreated);
}
private void HandleOrderCreated(OrderCreatedEvent orderEvent)
{
// 发送邮件通知
SendOrderConfirmationEmail(orderEvent.CustomerEmail, orderEvent.OrderId);
}
private void SendOrderConfirmationEmail(string email, string orderId)
{
Console.WriteLine($"发送订单确认邮件至 {email},订单号:{orderId}");
}
}
public class InventoryService
{
public InventoryService(EventBus eventBus)
{
// 订阅订单创建事件
eventBus.Subscribe<OrderCreatedEvent>(HandleOrderCreated);
}
private void HandleOrderCreated(OrderCreatedEvent orderEvent)
{
// 更新库存
UpdateInventory(orderEvent.OrderId);
}
private void UpdateInventory(string orderId)
{
Console.WriteLine($"更新库存,处理订单 {orderId}");
}
}
}
C#namespace AppEvent
{
internal class Program
{
static void Main(string[] args)
{
var eventBus = new EventBus();
// 注册服务
var orderService = new OrderService(eventBus);
var notificationService = new NotificationService(eventBus);
var inventoryService = new InventoryService(eventBus);
// 创建订单
orderService.CreateOrder("customer123", 199.99m);
Console.ReadKey();
}
}
}
事件驱动架构是现代软件设计中解耦应用的强大工具。通过将系统拆分为事件发布者和订阅者,我们可以构建更加灵活、可维护的软件系统。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!