C# 代理模式

代理(Proxy)模式的核心思想可以表述为:

代理是一个"替身"对象,它控制对原始对象(目标对象)的访问,并在调用前后插入额外逻辑(如日志、事务、权限检查等),而客户端通常 unaware(无感知)自己正在和代理交互。


✅ 一、代理的本质:包装 + 增强

角色 作用
目标对象(Target) 真正干活的类(如 OrderService
代理对象(Proxy) 外表看起来和目标一模一样,但内部会先做些额外事情,再决定是否/如何调用目标
客户端(Client) 只知道接口或基类,不知道实际用的是目标还是代理

🔍 二、举个生活化的例子 🌰

想象你请了一个私人助理(Proxy)

  • 你想见 CEO(目标对象)
  • 但 CEO 很忙,不会直接见你
  • 你只能联系助理
  • 助理会:
    • 先检查你的预约(权限验证)
    • 记录你来访的时间(日志)
    • 确认 CEO 有空才带你进去(调用真实方法)
    • 甚至有时候直接替 CEO 回答你(缓存)

💼 你感觉是在和 CEO 沟通,其实全程是助理在处理。


💻 三、代码示例:静态代理 vs 动态代理

1️⃣ 静态代理(手写)

csharp 复制代码
public interface IOrderService
{
    void CreateOrder(string id);
}

// 真实服务
public class OrderService : IOrderService
{
    public void CreateOrder(string id) => Console.WriteLine($"创建订单: {id}");
}

// 手写的代理类
public class LoggingOrderProxy : IOrderService
{
    private readonly IOrderService _realService;

    public LoggingOrderProxy(IOrderService realService)
    {
        _realService = realService;
    }

    public void CreateOrder(string id)
    {
        Console.WriteLine("【日志】开始创建订单");
        _realService.CreateOrder(id); // 调用真实对象
        Console.WriteLine("【日志】订单创建完成");
    }
}

// 客户端使用
var proxy = new LoggingOrderProxy(new OrderService());
proxy.CreateOrder("123"); 
// 输出:
// 【日志】开始创建订单
// 创建订单: 123
// 【日志】订单创建完成

✅ 客户端只依赖 IOrderService,完全不知道背后是代理还是真实对象。


2️⃣ 动态代理(如 Castle DynamicProxy、.NET 的 RealProxy

你不用手写代理类,框架在运行时自动生成

csharp 复制代码
// 使用 Castle DynamicProxy
var generator = new ProxyGenerator();
var interceptor = new LoggingInterceptor();

// 动态生成一个 IOrderService 的代理对象
var proxy = generator.CreateInterfaceProxyWithTarget<IOrderService>(
    target: new OrderService(),
    interceptor: interceptor
);

proxy.CreateOrder("123"); // 自动触发拦截器逻辑

其中 LoggingInterceptor 定义增强逻辑:

csharp 复制代码
public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine($"【拦截】调用方法: {invocation.Method.Name}");
        invocation.Proceed(); // 调用真实方法
        Console.WriteLine($"【拦截】方法结束");
    }
}

🔸 这个代理类是运行时动态生成的 IL 代码,不是你写的,但行为和静态代理一致。


✅ 四、代理的常见用途

场景 说明
AOP(面向切面编程) 日志、性能监控、异常处理
安全控制 权限验证、访问拦截
延迟加载(Lazy Load) 如 EF Core 的导航属性代理
缓存 先查缓存,没有再调真实对象
远程调用(RPC) 本地代理代表远程服务(如 WCF)
测试 Mock 单元测试中用 Mock 代理替代真实依赖

🆚 五、代理 vs 装饰器(Decorator)?

很多人会混淆代理和装饰器,其实:

代理(Proxy) 装饰器(Decorator)
目的 控制访问(侧重"管控") 增强功能(侧重"扩展")
关系 通常隐藏真实对象 明确组合并暴露增强行为
透明性 客户端通常不知情 客户端可能知道被装饰了
例子 权限代理、远程代理 给流加缓冲、加密

但在代码结构上,两者非常相似,代理可以看作是一种特殊的装饰器


"代理的大概意思就是生成的这个新类代替原来的类进行一些操作的意思"

更完整地说:
代理是一个与原类具有相同接口(或继承关系)的新类,它"代替"原类接收调用,并在适当时机决定是否、何时、如何调用原类的方法,同时可插入额外逻辑。

而现代框架(如 ASP.NET Core 的 DI、Entity Framework、Castle、Autofac)大量使用动态代理来实现 AOP、懒加载、事务管理等,而你作为开发者几乎无需关心底层生成过程。


如果你正在用类似 Castle 或 .NET 的拦截机制,现在你应该明白:

那个"看不见的代理类",就是你真实服务的"替身保镖" 👮‍♂️✨

相关推荐
程序员大雄学编程2 小时前
用Python来学微积分34-定积分的基本性质及其应用
开发语言·python·数学·微积分
liu****2 小时前
12.线程(二)
linux·开发语言·c++·1024程序员节
DKPT2 小时前
如何设置JVM参数避开直接内存溢出的坑?
java·开发语言·jvm·笔记·学习
林一百二十八2 小时前
Python实现手写数字识别
开发语言·python
小小鱼儿飞3 小时前
QT Quick QML项目音乐播放器16----无边框窗口拖动、小窗播放、隐藏系统托盘
开发语言·qt
-指短琴长-3 小时前
Qt的下载和安装【Windows】
开发语言·windows·qt
不会编程的小寒3 小时前
C++ this指针、常函数、内联函数
java·开发语言
小冯的编程学习之路3 小时前
【C++】:C++基于微服务的即时通讯系统(2)
开发语言·c++·微服务
许长安3 小时前
C/C++中的extern关键字详解
c语言·开发语言·c++·经验分享·笔记