castle.dynamicProxy学习笔记
目的:
可以将castle.dynamicProxy当成代码生成器,快速的生成自己想的代码.这个库经历了这么多年的测试,应该可以用了:D
概念:
IInterceptor:拦截器
当方法(属性的本质是两个方法的组合)被调用时,则执行这个拦截器的代码.
但是,默认情况下,一个方法的调用被生成了一个拦截器.如果用于DC代码生成,这似乎有点浪费资源.
public class SimpleLogInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine(">>" + invocation.Method.Name); invocation.Proceed(); } }
测试:
ProxyGenerator generator = new ProxyGenerator();
SimpleSamepleEntity entity = generator.CreateClassProxy<SimpleSamepleEntity>( new SimpleLogInterceptor(), new CallingLogInterceptor()); //这里可以指定多个拦截器 entity.Name = "Richie"; entity.Age = 50; Console.WriteLine("The entity is: " + entity); Console.WriteLine("Type of the entity: " + entity.GetType().FullName); Console.ReadKey();
IInterceptorSelector 与 IProxyGenerationHook
实际中并不一定所有方法都需要运用全部的拦截器,对方法调用有选择性的选择拦截器有2种方式,例如:
public class InterceptorSelector : IInterceptorSelector { public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors) { if (method.Name.StartsWith("set_")) return interceptors; //这里可以决定什么的方法返回什么样的拦截器 else return interceptors.Where(i => i is CallingLogInterceptor).ToArray<IInterceptor>(); } }
public class InterceptorFilter : IProxyGenerationHook { public bool ShouldInterceptMethod(Type type, MethodInfo memberInfo) { return memberInfo.IsSpecialName && (memberInfo.Name.StartsWith("set_") || memberInfo.Name.StartsWith("get_")); //什么样的方法可以被拦截? } public void NonVirtualMemberNotification(Type type, MemberInfo memberInfo) {
//类型为非虚方法时,这里可以得到提示,将被调用 } public void MethodsInspected() { } }
测试代码:
ProxyGenerator generator = new ProxyGenerator(); var options = new ProxyGenerationOptions(new InterceptorFilter()) { Selector = new InterceptorSelector() }; SimpleSamepleEntity entity = generator.CreateClassProxy<SimpleSamepleEntity>( options, new SimpleLogInterceptor(), new CallingLogInterceptor()); entity.Name = "Richie"; entity.Age = 50; Console.WriteLine("The entity is: " + entity); Console.WriteLine("Type of the entity: " + entity.GetType().FullName); Console.ReadKey();
IProxyGenerationHook接口决定整个方法是否运用拦截器,他是在动态构造代理类型的时候使用的;而IInterceptorSelector接口决定某个方法该运用哪些拦截器,他在每次调用被拦截的方法时执行
上面的示例只对setter和getter方法进行拦截,并且对getter方法只使用CallingLogInterceptor这个拦截器
导出、生成代理类型
Castle Dynamic Proxy允许我们将运行时生成的代理类型生成dll文件存到磁盘上,下次启动时通过加载这个dll文件可以避免动态生成代理类型
var scope = new ModuleScope( true, ModuleScope.DEFAULT_ASSEMBLY_NAME, ModuleScope.DEFAULT_FILE_NAME, "DynamicProxyTest.Proxies", "DynamicProxyTest.Proxies.dll"); var builder = new DefaultProxyBuilder(scope); var generator = new ProxyGenerator(builder); var options = new ProxyGenerationOptions(new InterceptorFilter()) { Selector = new InterceptorSelector() }; SimpleSamepleEntity entity = generator.CreateClassProxy<SimpleSamepleEntity>( options, new SimpleLogInterceptor(), new CallingLogInterceptor()); IStorageNode node = generator.CreateInterfaceProxyWithTargetInterface<IStorageNode>( new StorageNode("master") , new DualNodeInterceptor(new StorageNode("slave")) , new CallingLogInterceptor()); options = new ProxyGenerationOptions(); options.AddMixinInstance(new ClassA()); ClassB objB = generator.CreateClassProxy<ClassB>(options, new CallingLogInterceptor()); scope.SaveAssembly(false);
注意:上面用到的拦截器和其他测试类都必须加上[Serializable]属性
可以用reflector查看生成的dll,大致了解代理对象是如何工作的
启动时,可以使用
scope.LoadAssemblyIntoCache(assembly);
将生成的代理类型加载到内存中,其中assembly需要我们手动加载
参考原文:
http://www.cnblogs.com/RicCC/archive/2010/03/15/castle-dynamic-proxy.html
XAF开发成品案例参考
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
作者博客: http://www.cnblogs.com/foreachlife
欢迎加入CIIP框架\XAF技术应用交流群: 336090194 群文件中有更多相关工具及文档资料
转载请注明出处。多谢!
欢迎加我微信: admiralcn 或扫码:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端