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 = ;
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 = ;
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
castle.dynamicProxy学习笔记的更多相关文章
- Castle DynamicProxy基本用法(AOP)
本文介绍AOP编程的基本概念.Castle DynamicProxy(DP)的基本用法,使用第三方扩展实现对异步(async)的支持,结合Autofac演示如何实现AOP编程. AOP 百科中关于AO ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
随机推荐
- 魅力python------if - else 语句
引入:if-else的作用,满足一个条件做什么,否则做什么. if-else语句语法结构 if 判断条件: 要执行的代码 else: 要执行的代码 判断条件:一般为关系表达式或bool类型的值 执行过 ...
- Scala编程之访问修饰符
private ,protected,public,在不加前两者声明时为public为公共式访问: private为私有式访问:protected为家族式访问,与Java一致. object Oute ...
- ZT Android 4.2蓝牙介绍
Android 4.2蓝牙介绍 分类: Android开发系列 2013-06-27 14:16 7110人阅读 评论(22) 收藏 举报 目录(?)[-] Android 42蓝牙介绍 一 蓝牙规 ...
- 原生js实现一个DIV的碰撞反弹运动,并且添加重力效果
继上一篇... 原生js实现一个DIV的碰撞反弹运动,并且添加重力效果 关键在于边界检测,以及乘以的系数问题,实现代码并不难,如下: <!DOCTYPE html> <html la ...
- 在WebStorm中使用CSScomb
在前端开发写CSS时,往往不能很好的把握格式和属性顺序,阅读起来不友好.CSScomb帮助我们解决了这个问题! CSScomb(CSS梳理)是一个可以用来格式化和排序CSS属性的插件,官网地址http ...
- python第十六课——外部函数and内部函数
1.外部函数&内部函数 内部函数: 定义在某个函数的内部,就是内部函数: [注意事项]: 1).内部函数可以随意使用它外部函数中的内容 2).外部函数不能使用内部函数中的内容 3).内部函数不 ...
- 谷歌浏览器安装POSTMAN
1.下载postman插件,可以自己到网上下载,也可以点击http://download.csdn.net/detail/u010246789/9528471 2.解压文件,在解压后的文件夹中找到.c ...
- Lambda表达式学习(2)
在. net3. 5里面 , 委托的定义和实现被大大的简化了!使用关键字Func或Action就可以定义一个委托 , 使用拉姆达表达式就可以实现一个具体的委托. Func关键字是用来定义一个有返回值的 ...
- gulp合并压缩
1.文件合并压缩 var concat = require(‘gulp-concat’); //引用 var uglify = require(‘gulp-uglify’); 接下来,只要conca ...
- 【题解】洛谷P4158 [SCOI2009] 粉刷匠(DP)
次元传送门:洛谷P4158 思路 f[i][j][k][0/1]表示在坐标为(i,j)的格子 已经涂了k次 (0是此格子涂错 1是此格子涂对)涂对的格子数 显然的是 每次换行都要增加一次次数 那么当j ...