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; } }在实际项目中我经常发现开发者过度使用代理模式会导致系统复杂性增加。一个实用的建议是只有当确实需要控制访问或添加横切关注点时才使用代理对于简单的功能扩展继承或组合可能是更简单的选择。

相关新闻

Android开发:XUtils3环境搭建与核心功能详解

Android开发:XUtils3环境搭建与核心功能详解

1. XUtils3 环境搭建全流程解析 XUtils3 是 Android 开发中常用的工具库,它封装了网络请求、数据库操作、图片加载等常用功能。最近在帮团队搭建新项目时,发现很多新人对于如何正确集成 XUtils3 还存在困惑。这里分享下我在多个项目中总结的环境搭建方法…

2026/7/19 19:43:34 阅读更多 →
Windows 11系统清理优化终极指南:3步快速提升性能与隐私保护

Windows 11系统清理优化终极指南:3步快速提升性能与隐私保护

Windows 11系统清理优化终极指南:3步快速提升性能与隐私保护 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter …

2026/7/19 19:43:34 阅读更多 →
AI产品不是软件:概率性治理与可存活失败设计

AI产品不是软件:概率性治理与可存活失败设计

1. 项目概述:这不是软件,是全新物种的诞生现场你有没有过这种感觉:花三个月打磨出一个AI功能,上线后用户反馈“偶尔答得离谱”,技术团队立刻拉群排查——结果发现模型代码没改、API调用正常、日志里连个报错都没有。最…

2026/7/19 19:43:34 阅读更多 →

最新新闻

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

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

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

2026/7/20 0:15:40 阅读更多 →
ngx_output_chain_get_buf

ngx_output_chain_get_buf

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…

2026/7/20 0:13:39 阅读更多 →
python数据可视化技巧的100个练习 -- 31. 类别数据的点图

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

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

2026/7/20 0:12:39 阅读更多 →
智能体走进物理世界,千里科技携舱驾协同成果亮相WAIC 2026

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

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

2026/7/20 0:12:39 阅读更多 →
商汤大装置发布“技术-生态-商业”闭环布局,共启“国产AI基础设施规模化商用元年”

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

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

2026/7/20 0:12:39 阅读更多 →
2026年具身智能领域代表性机器人产品观察:普渡一脑多形底座与实景落地解析

2026年具身智能领域代表性机器人产品观察:普渡一脑多形底座与实景落地解析

前言2026年被行业视为具身智能从"实验室炫技"走向"规模化量产"的关键拐点。据弗若斯特沙利文《全球商用服务机器人市场研究报告》,普渡科技以23%市占率位居全球商用服务机器人第一,业务覆盖85+个国家和地区,累…

2026/7/20 0:11:39 阅读更多 →

日新闻

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

7月18日智东西消息,在2026 WAIC期间,努比亚联合字节豆包打造的二代“豆包手机”努比亚NaviX Ultra首次亮相,相比一代有诸多升级。智能体手机理念中兴通讯终端事业部总裁、努比亚总裁倪飞表示,智能体手机要从人操作手机变为手机帮人…

2026/7/20 0:00:34 阅读更多 →
努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra:外观与功能双升级在2026 WAIC期间,首次亮相的努比亚NaviX Ultra吸引了众多目光。它是努比亚联合字节豆包打造的二代“豆包手机”,与一代努比亚M153相比,外观设计变化较大。其机身背部搭载横向排布的大尺寸影像模…

2026/7/20 0:00:34 阅读更多 →
C# 将逗号分割的字符串转换为long,并添加到List<long>

C# 将逗号分割的字符串转换为long,并添加到List<long>

目录 方法1:使用Split和Convert.ToInt64 方法2:使用LINQ的Select和ToList 方法3:使用TryParse进行异常安全转换(推荐) 如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天…

2026/7/20 0:00:34 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/20 5:57:49 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/20 4:31:26 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/20 5:56:42 阅读更多 →

月新闻