C#代理模式详解与应用实践

发布时间:2026/7/19 19:45:02

C#代理模式详解与应用实践
1. C#代理模式深度解析在C#开发中代理模式Proxy Pattern是一种结构型设计模式它为其他对象提供一种代理以控制对这个对象的访问。这种模式在需要控制对象访问权限、延迟加载或添加额外功能时特别有用。1.1 代理模式的核心概念代理模式主要包含三个角色Subject抽象主题定义真实主题和代理主题的共同接口RealSubject真实主题实现真正的业务逻辑Proxy代理持有真实主题的引用控制对真实主题的访问// 抽象主题接口 public interface ISubject { void Request(); } // 真实主题 public class RealSubject : ISubject { public void Request() { Console.WriteLine(RealSubject: Handling Request.); } } // 代理类 public class Proxy : ISubject { private RealSubject _realSubject; public void Request() { if (_realSubject null) { _realSubject new RealSubject(); } // 可以在调用真实对象前后添加额外逻辑 Console.WriteLine(Proxy: Pre-processing); _realSubject.Request(); Console.WriteLine(Proxy: Post-processing); } }1.2 代理模式的典型应用场景虚拟代理延迟创建开销大的对象保护代理控制对原始对象的访问权限远程代理为位于不同地址空间的对象提供本地代表智能引用在访问对象时执行额外操作如引用计数提示在.NET框架中WCF服务就是使用代理模式的典型例子客户端通过服务代理与远程服务通信。2. C#动态代理实现2.1 使用RealProxy实现动态代理.NET框架提供了RealProxy类来实现动态代理using System.Runtime.Remoting.Proxies; using System.Runtime.Remoting.Messaging; public class LoggingProxy : RealProxy { private readonly object _target; public LoggingProxy(object target) : base(target.GetType()) { _target target; } public override IMessage Invoke(IMessage msg) { var methodCall msg as IMethodCallMessage; Console.WriteLine($Before invoking {methodCall.MethodName}); try { var result methodCall.MethodBase.Invoke(_target, methodCall.Args); Console.WriteLine($After invoking {methodCall.MethodName}); return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall); } catch (Exception ex) { Console.WriteLine($Error in {methodCall.MethodName}: {ex.Message}); return new ReturnMessage(ex, methodCall); } } } // 使用示例 public interface IService { void DoWork(); } public class Service : IService { public void DoWork() { Console.WriteLine(Doing actual work...); } } var service new Service(); var proxy new LoggingProxy(service); var serviceProxy (IService)proxy.GetTransparentProxy(); serviceProxy.DoWork();2.2 使用Castle DynamicProxyCastle DynamicProxy是一个流行的动态代理库using Castle.DynamicProxy; public class LoggingInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine($Before {invocation.Method.Name}); invocation.Proceed(); Console.WriteLine($After {invocation.Method.Name}); } } // 使用示例 var generator new ProxyGenerator(); var service new Service(); var proxy generator.CreateInterfaceProxyWithTargetIService( service, new LoggingInterceptor()); proxy.DoWork();3. 代理模式的高级应用3.1 AOP编程实现面向切面编程AOP常使用代理模式实现public class CacheAspect : IInterceptor { private readonly MemoryCache _cache MemoryCache.Default; public void Intercept(IInvocation invocation) { var cacheKey ${invocation.TargetType.FullName}.{invocation.Method.Name}; if (_cache.Contains(cacheKey)) { invocation.ReturnValue _cache.Get(cacheKey); return; } invocation.Proceed(); _cache.Add(cacheKey, invocation.ReturnValue, DateTimeOffset.Now.AddMinutes(5)); } } // 使用示例 var generator new ProxyGenerator(); var service new Service(); var cachedService generator.CreateInterfaceProxyWithTargetIService( service, new CacheAspect());3.2 性能监控代理public class PerformanceMonitorProxy : IInterceptor { public void Intercept(IInvocation invocation) { var stopwatch Stopwatch.StartNew(); invocation.Proceed(); stopwatch.Stop(); Console.WriteLine(${invocation.Method.Name} executed in {stopwatch.ElapsedMilliseconds}ms); } }4. 代理模式的注意事项与最佳实践4.1 常见问题与解决方案接口代理与类代理的区别接口代理只能拦截接口方法类代理可以拦截虚方法virtual性能考虑动态代理会引入一定的性能开销对于性能敏感场景考虑使用编译时代理如Source Generators循环引用问题代理对象持有真实对象引用可能导致内存泄漏实现IDisposable接口确保资源释放4.2 最佳实践保持代理轻量级代理类不应包含复杂业务逻辑明确代理目的每个代理类应专注于单一功能如日志、缓存合理使用组合可以通过组合多个代理实现复杂功能考虑线程安全确保代理在多线程环境下正常工作// 线程安全的代理示例 public class ThreadSafeProxy : ISubject { private readonly ISubject _realSubject; private readonly object _lock new object(); public ThreadSafeProxy(ISubject realSubject) { _realSubject realSubject; } public void Request() { lock (_lock) { _realSubject.Request(); } } }5. 代理模式与其他模式的比较5.1 代理模式与装饰器模式特性代理模式装饰器模式目的控制访问添加功能对象创建通常由代理控制通常由客户端控制关注点访问控制、延迟加载等动态添加职责5.2 代理模式与适配器模式特性代理模式适配器模式目的控制访问转换接口接口关系相同接口不同接口使用场景访问控制、缓存等集成不兼容接口6. 实际项目中的应用案例6.1 ORM框架中的延迟加载public class ProductProxy : Product { private bool _isLoaded; private readonly FuncProduct _loader; public ProductProxy(FuncProduct loader) { _loader loader; } public override string Name { get { if (!_isLoaded) { var realProduct _loader(); // 复制属性值 _isLoaded true; } return base.Name; } set base.Name value; } }6.2 Web API客户端代理public class ApiClientProxy : IApiClient { private readonly HttpClient _httpClient; private readonly ILogger _logger; public ApiClientProxy(HttpClient httpClient, ILogger logger) { _httpClient httpClient; _logger logger; } public async TaskResponse GetDataAsync(Request request) { _logger.LogInformation(Sending request to API); try { var response await _httpClient.PostAsJsonAsync(api/endpoint, request); response.EnsureSuccessStatusCode(); return await response.Content.ReadAsAsyncResponse(); } catch (Exception ex) { _logger.LogError(ex, API request failed); throw; } } }7. 性能优化与高级技巧7.1 代理缓存策略public class ProxyCacheT where T : class { private static readonly ConcurrentDictionaryType, T _cache new(); private readonly FuncT _factory; public ProxyCache(FuncT factory) { _factory factory; } public T GetProxy() { return _cache.GetOrAdd(typeof(T), _ { var generator new ProxyGenerator(); return generator.CreateInterfaceProxyWithoutTargetT(new LoggingInterceptor()); }); } }7.2 轻量级代理实现对于性能敏感场景可以手动实现轻量级代理public class LightweightProxyT : DispatchProxy where T : class { private T _decorated; private ActionT _preAction; private ActionT _postAction; protected override object Invoke(MethodInfo targetMethod, object[] args) { _preAction?.Invoke(_decorated); var result targetMethod.Invoke(_decorated, args); _postAction?.Invoke(_decorated); return result; } public static T Create(T decorated, ActionT preAction null, ActionT postAction null) { object proxy CreateT, LightweightProxyT(); ((LightweightProxyT)proxy).SetParameters(decorated, preAction, postAction); return (T)proxy; } private void SetParameters(T decorated, ActionT preAction, ActionT postAction) { _decorated decorated ?? throw new ArgumentNullException(nameof(decorated)); _preAction preAction; _postAction postAction; } }8. 测试与调试代理类8.1 单元测试策略[TestClass] public class ProxyTests { [TestMethod] public void LoggingProxy_ShouldLogMethodCalls() { // Arrange var logger new StringWriter(); Console.SetOut(logger); var service new Service(); var proxy new LoggingProxy(service); var serviceProxy (IService)proxy.GetTransparentProxy(); // Act serviceProxy.DoWork(); // Assert var log logger.ToString(); Assert.IsTrue(log.Contains(Before invoking DoWork)); Assert.IsTrue(log.Contains(After invoking DoWork)); } }8.2 调试技巧检查代理类型使用GetType()查看代理对象的实际类型断点设置在拦截器或代理方法中设置断点日志记录详细记录代理的调用过程和参数性能分析使用性能分析工具测量代理引入的开销9. 现代C#中的代理模式演进9.1 Source Generators实现编译时代理C# 9.0引入的Source Generators可以在编译时生成代理代码[Generator] public class ProxyGenerator : ISourceGenerator { public void Execute(GeneratorExecutionContext context) { // 分析上下文中的接口类型 // 生成代理类源代码 // 添加到编译上下文 } public void Initialize(GeneratorInitializationContext context) { // 初始化逻辑 } }9.2 使用DefaultInterfaceMethod实现代理C# 8.0的默认接口方法可以用于简单代理场景public interface IService { void DoWork() { Console.WriteLine(Default implementation); } } public class ServiceProxy : IService { private readonly IService _realService; public ServiceProxy(IService realService) { _realService realService; } void IService.DoWork() { Console.WriteLine(Proxy pre-processing); _realService.DoWork(); Console.WriteLine(Proxy post-processing); } }10. 安全考虑与边界情况10.1 安全代理实现public class SecurityProxy : ISubject { private readonly ISubject _realSubject; private readonly IPrincipal _principal; public SecurityProxy(ISubject realSubject, IPrincipal principal) { _realSubject realSubject; _principal principal; } public void Request() { if (!_principal.IsInRole(Admin)) { throw new SecurityException(Access denied); } _realSubject.Request(); } }10.2 处理特殊边界情况异步方法代理确保正确处理async/awaitref/out参数在拦截器中正确处理参数传递泛型方法确保类型参数正确传递事件处理代理类应正确转发事件public class AsyncProxy : IAsyncService { private readonly IAsyncService _realService; public AsyncProxy(IAsyncService realService) { _realService realService; } public async Taskstring GetDataAsync() { Console.WriteLine(Before async call); var result await _realService.GetDataAsync(); Console.WriteLine(After async call); return result; } }在实际项目中我经常发现开发者过度使用代理模式会导致系统复杂性增加。一个实用的建议是只有当确实需要控制访问或添加横切关注点时才使用代理对于简单的功能扩展继承或组合可能是更简单的选择。

相关新闻

终极Mihon漫画阅读器指南:如何在Android上免费管理你的漫画收藏

终极Mihon漫画阅读器指南:如何在Android上免费管理你的漫画收藏

2026/7/19 19:45:02

终极Mihon漫画阅读器指南:如何在Android上免费管理你的漫画收藏 【免费下载链接】mihon Free and open source manga reader for Android 项目地址: https://gitcode.com/gh_mirrors/mi/mihon 你是否曾在手机里下载了几十部漫画,却找不到合适的方…

C语言学习指南:从基础到项目实战

C语言学习指南:从基础到项目实战

2026/7/19 19:45:02

1. C语言的前世今生C语言诞生于1972年贝尔实验室,由丹尼斯里奇(Dennis Ritchie)在开发UNIX操作系统时创造。它最初是作为B语言的改进版本出现的,但很快发展成一门独立的编程语言。有趣的是,C语言的"K&R"…

深度解析Windows游戏兼容层架构:DxWrapper实现原理与高级配置指南

深度解析Windows游戏兼容层架构:DxWrapper实现原理与高级配置指南

2026/7/19 19:45:02

深度解析Windows游戏兼容层架构:DxWrapper实现原理与高级配置指南 【免费下载链接】dxwrapper Fixes compatibility issues with older games running on Windows 10/11 by wrapping DirectX dlls. Also allows loading custom libraries with the file extension .…

python数据可视化技巧的100个练习 -- 31. 类别数据的点图

python数据可视化技巧的100个练习 -- 31. 类别数据的点图

2026/7/20 0:15:16

重要性★★★☆☆ 难度★★☆☆☆ 你是一家零售公司的数据分析师。你的经理要求你可视化最近产品发布的客户满意度评级分布。评级是分类的,范围从“非常不满意”到“非常满意”。创建一个点图以显示每个评级类别的频率。使用 Python 进行数据处理和可视化。在代码中生成输入…

智能体走进物理世界,千里科技携舱驾协同成果亮相WAIC 2026

智能体走进物理世界,千里科技携舱驾协同成果亮相WAIC 2026

2026/7/20 0:15:16

在2026世界人工智能大会(WAIC 2026)举办期间,千里科技董事长、阶跃星辰董事长印奇作为特邀嘉宾出席大会开幕式并在大会主论坛(上午场)发表主题演讲《当智能体进入物理世界》。在印奇看来,"智能体"…

商汤大装置发布“技术-生态-商业”闭环布局,共启“国产AI基础设施规模化商用元年”

商汤大装置发布“技术-生态-商业”闭环布局,共启“国产AI基础设施规模化商用元年”

2026/7/20 0:15:16

7月18日,在WAIC 2026商汤科技 “基座大模型架构创新与生态合作论坛”上,商汤科技联合创始人、大装置事业群总裁杨帆发表《智变共生——加速AI基础设施持续升级》主题演讲,系统呈现了商汤大装置国产AI基础设施“技术-生态-商业”闭环布局&…

ngx_output_chain_get_buf

ngx_output_chain_get_buf

2026/7/20 0:15:16

1 定义 ngx_output_chain_get_buf 函数 定义在 src/core/ngx_output_chain.cstatic ngx_int_t ngx_output_chain_get_buf(ngx_output_chain_ctx_t *ctx, off_t bsize) {size_t size;ngx_buf_t *b, *in;ngx_uint_t recycled;in ctx->in->buf;size ctx->buf…

互联网大厂常见Java面试题及答案汇总(2026持续更新)

互联网大厂常见Java面试题及答案汇总(2026持续更新)

2026/7/20 0:15:16

金九银十即将来袭,又是一个跳槽的好季节,准备跳槽的同学都摩拳擦掌准备大面好几场,今天为大家准备了互联网面试必备的 1 到 5 年 Java 面试者都需要掌握的面试题,分别 JVM,并发编程,MySQL,Tomca…

STM32H7 QSPI Flash下载算法制作指南

STM32H7 QSPI Flash下载算法制作指南

2026/7/20 0:05:15

1. STM32H7 QSPI Flash下载算法制作概述在STM32H7系列微控制器的开发过程中,外部QSPI Flash存储器常被用于扩展存储空间。然而,MDK开发环境默认并不支持所有型号的QSPI Flash编程,这就需要我们自行制作下载算法。本文将详细介绍如何为STM32H7…

微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

2026/7/20 2:32:48

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

2026/7/20 2:33:13

一、零售门店全域协同业务背景与行业痛点 1.1 门店超级终端设备矩阵(连锁便利店/商超标准配置) 自助收银Kiosk一体机:顾客结算、自助核销优惠券、商品素材预览;运营折叠平板:店长后台商品上新、图片录入、活动配置、…

噗叽短视频界面分析

噗叽短视频界面分析

2026/7/20 2:32:14

1 和小红书类似,可以采用类似判断方法------------其实他比小红书好判断,因为他没有图片,控件位置几乎是固定的,都不用判断------------2 因为他没有点赞按钮------------而且几乎所有控件位置都是完全一样的,所以我就…

SoC超时垫片机制:从硬件原理到软件实战的可靠性设计

SoC超时垫片机制:从硬件原理到软件实战的可靠性设计

2026/7/20 0:05:15

1. 系统互联中的“守门员”:超时与异常响应处理机制在复杂的SoC(片上系统)设计中,处理器核心、内存控制器、外设等数十甚至上百个IP模块通过高速片上互联网络(如VBUSM、AXI、CHI)进行通信。这个网络就像一座…

一键批量建文件夹工具省时间效率神器

一键批量建文件夹工具省时间效率神器

2026/7/20 0:05:15

软件介绍 批量创建文件夹这事听起来简单,右键新建就行,但真要你一口气建几十个、上百个的时候,你才知道有多崩溃。今天这款工具就是专门治这个病的,而且玩法特别——它根本不是传统意义上的软件,就是一个Excel表格。 …

C++短信服务开发实践:从SMPP协议到高并发架构设计

C++短信服务开发实践:从SMPP协议到高并发架构设计

2026/7/20 0:05:15

1. 项目概述:为什么我们需要自己动手搭建短信服务?在当前的互联网产品开发中,短信验证码、通知提醒、营销推广几乎是标配功能。很多开发者,尤其是刚入行的朋友,第一反应是去集成阿里云、腾讯云等大厂的短信服务SDK。这…