Castle.DynamicProxy Part 1: ClassProxy
1.Castle中代理对象的分类
总的来说,代理对象大概可以分为2大类:
1.继承类型的代理对象
一类是继承类型的代理类。即:有一个类A,它的代理类是B。B是继承自A的。调用代理类B中的方法时,可以通过拦截器做一些逻辑判断等等。但注意,A中的类只能是virtual的才可以被代理。C#中只有virtual方法才能被override。
这种代理类在castle的动态代理中只有一种,就是ClassProsy。也是最简单,最容易理解的一种代理类。
2.组合类型的代理对象
还有一类是组合型的代理类。即有一个类A,它的代理类是B。B不是继承自A的,而是B中包含了一个A的实例。这种代理就没有限制A中的方法必须是virtual的。
这种代理类型在castle的动态代理中有如下几种:
- class proxy with target
- interface proxy without target
- interface proxy with target
- interface proxy with target interface
这几种代理类将在后续的文章中进行分别说明。
2.一个简单的classProxy例子
准备一个汽车类,这个类在后面将会被代理
创建一个简单的汽车类:为保持这个demo的简单,该类现在只有2个虚方法:Start和Stop。
public class Car
{public virtual void Start()
{
Console.WriteLine("启动");
} public virtual void Stop()
{
Console.WriteLine("停止");
}
}
创建一个拦截器
创建一个简单的拦截器,这个拦截器只是很简单的在方法调用前和调用后打印一句话。
public class SimpleInterceptor : Castle.Core.Interceptor.IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("begin invoke");
invocation.Proceed();
Console.WriteLine("end invoke");
}
}
创建Car类的一个代理
使用ProxyGenerator的CreateClassProxy方法来创建一个代理。然后调用代理类的start和end方法。
public class ClassProxyDemo
{
public void Main()
{
SimpleInterceptor interceptor = new SimpleInterceptor(); //给Car类生成代理
ProxyGenerator generator = new ProxyGenerator();
var car = generator.CreateClassProxy<Car>(new IInterceptor[]{interceptor});
car.Start();
car.Stop();
}
}
可以想象一下,在调用start和end方法之前应该都会在控制台中打印出相应内容。以下是输出结果,和我们的预想一致。
------ Test started: Assembly: Castle.DynamicProxy.Demo.dll ------ begin invoke
启动
end invoke
begin invoke
停止
end invoke 1 passed, 0 failed, 0 skipped, took 0.21 seconds (Ad hoc).
将类的方法修改为非virtual
如果将Car类的Stop方法改成非虚类,结果会是怎么样呢?
public void Stop()
{
Console.WriteLine("停止");
}
输出的日志为:
------ Test started: Assembly: Castle.DynamicProxy.Demo.dll ------ begin invoke
启动
end invoke
停止 1 passed, 0 failed, 0 skipped, took 0.21 seconds (Ad hoc).
可以看到,只有start方法被拦截到了。stop方法没有没拦截到。
在使用ClassProxy代理时,只有类的vierual方法,或者virtual属性才可以被代理。
3.DynamicProxy中的拦截器
首先看下Interceptor借口的定义吧:
#region Assembly Castle.Core.dll, v1.1.0.0
#endregion
namespace Castle.Core.Interceptor
{
// Summary:
// New interface that is going to be used by DynamicProxy 2
public interface IInterceptor
{
void Intercept(IInvocation invocation);
}
}
IInvocation接口封装了对当前方法调用的所有信息。它的成员如下所示:
下面让我们来对拦截器做一些改进:
改进1:获取拦截方法的名称
我们希望拦截器中可以告诉我们当前是哪个方法被调用了,这个很简单,直接调用invocatiion.method的name属性即可。
var metodInfo = invocation.Method;
string methodName = metodInfo.Name;
改进2:让拦截器有限速功能
car是可以加速的,但是如果car的速度过高,我们就不允许加速了。为了实现这个功能,我们需要在car类中添加一个字段和属性来表述当前速度。
private int _speed;
public virtual int Speed { get { return _speed; } }
在拦截器中进行判断,如果调用的是Accelerate方法,就判断,加速后的速度是否超速(>60)。如果不,允许加速。否则,不执行加速。
public class SimpleInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
var metodInfo = invocation.Method;
string methodName = metodInfo.Name; var car = invocation.InvocationTarget as Car;
if(invocation.Arguments.Any())
{
int speed = (int)invocation.Arguments[0]; if (methodName == "Accelerate" && car.Speed + speed > 60)
{
Console.WriteLine("speed is too high...");
return;
}
} invocation.Proceed();}
}
如果被代理类中的属性是virtual的,也可以被拦截。拦截的方法名是get_属性名。如访问代理类的Speed属性,被拦截的方法是:get_Speed。
可以使用invocation.InvocationTarget as Car来访问代理类的实例。这样可以访问代理类中的属性等。在本例中是访问代理类的Speed属性。
4.最终代码
using System;
using System.Linq;
using Castle.Core.Interceptor;
using Castle.DynamicProxy; namespace DotNetDemos.Castle.DynamicProxy2
{
public class ClassProxyDemo
{
public void Main()
{
SimpleInterceptor interceptor = new SimpleInterceptor(); //给?Car类à生ú成é代ú理í
ProxyGenerator generator = new ProxyGenerator();
var car = generator.CreateClassProxy<Car>(new IInterceptor[] { interceptor });
//car.Start();
//car.Stop();
//car.Accelerate(40);
//car.Accelerate(40);
int speed= car.GetSpeed();
Console.WriteLine(speed);
}
} public class SimpleInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
var metodInfo = invocation.Method;
string methodName = metodInfo.Name; var car = invocation.InvocationTarget as Car;
if(invocation.Arguments.Any())
{
int speed = (int)invocation.Arguments[0]; if (methodName == "Accelerate" && car.Speed + speed > 60)
{
Console.WriteLine("speed is too high...");
return;
}
} Console.WriteLine("begin invoke {0} ",methodName); if (methodName == "GetSpeed")
{
invocation.ReturnValue = 200;
}
else
{
invocation.Proceed();
}
Console.WriteLine("end invoke {0} ",methodName);
}
} public class Car
{
private int _speed; public int Speed { get { return _speed; } } public virtual void Start()
{
Console.WriteLine("启动");
} public virtual void Stop()
{
Console.WriteLine("停止");
} public virtual void Accelerate(int speed)
{
_speed += speed;
Console.WriteLine("加速: +{0}",speed);
} public virtual void Decelerate(int speed)
{
_speed -= speed;
Console.WriteLine("减速: -{0}",speed);
} public virtual int GetSpeed()
{
return _speed;
}
} }
5.总结
本篇中介绍的ClassProxy是Castle的代理对象中唯一的一个继承类型的代理,这种代理要求被代理类的方法和属性必须是virtual的,侵入性比较强。和基于组合的代理对象相比,这种ClassProxy是相对比较简单的。接下来,会介绍Castel中的基于组合的代理对象,都是一些接口代理。功能更强大,在实际场景中也使用的更多。
关于ClassProxy在实际项目中的使用场景,目前还不太清楚。。待研究。NHibernate的实体类映射时,实体的属性都要求是virtual的,应该是使用的ClassProxy。
Castle.DynamicProxy Part 1: ClassProxy的更多相关文章
- 基于Autofac, Castle.DynamicProxy的动态WCF解决方案(原创)
本方案解决了下面3个主要的问题: 1.减少配置,为了避免每次新增service都需要去修改配置文件,包括服务器端跟各个客户端的. 2.能够使用函数重载,泛型函数,以及泛型类. 3.使项目能够快速地在w ...
- Castle DynamicProxy
Introduction¶ Castle DynamicProxy is a library for generating lightweight .NET proxies on the fly at ...
- castle.dynamicProxy学习笔记
目的: 可以将castle.dynamicProxy当成代码生成器,快速的生成自己想的代码.这个库经历了这么多年的测试,应该可以用了:D 概念: IInterceptor:拦截器 当方法(属性的本质是 ...
- Castle DynamicProxy基本用法(AOP)
本文介绍AOP编程的基本概念.Castle DynamicProxy(DP)的基本用法,使用第三方扩展实现对异步(async)的支持,结合Autofac演示如何实现AOP编程. AOP 百科中关于AO ...
- 使用Castle DynamicProxy (AOP)
在本文中,我将引导您了解.NET环境中的面向方面编程(AOP)概念,以及如何使用Castle DynamicProxy创建和附加方面.在我们开始之前,让我快速介绍AOP和 IoC.如果您已经熟悉这些 ...
- 在 CAP 中使用 AOP ( Castle.DynamicProxy )
简介 本篇文章主要介绍如何在 CAP 中集成使用 Castle.DynamicProxy,Castle DynamicProxy 是一个用于在运行时动态生成轻量级.NET代理的库.代理对象允许在不修改 ...
- AOP之Castle DynamicProxy 动态代理
这里主要介绍使用castle这个动态代理,在.net一些开源的框架里可以找到它的影子,就连微软的rchard也是使用这个进行方法拦截等可以基于这个进行方法拦截,在这个方面PostSharp算是比较好用 ...
- 几种Aop实现及Castle.DynamicProxy的使用
AoP(Aspect Oriented Programming,面向切面编程) .Net平台AOP技术研究 简单实现 通过继承实现 public interface ICoding { void Do ...
- Castle DynamicProxy creation出现COMException(0x800703fa)错误的解决方案
昨天有客户反馈周末重启服务器后,几台服务器上的应用运行全部出错.大致错误内容如下: COMException(0x800703fa):试图在标记为删除的注册表项上进行不合法的操作. 通过查看异常堆栈, ...
随机推荐
- DevExpress XtraReports 入门五 创建交叉表报表
原文:DevExpress XtraReports 入门五 创建交叉表报表 本文只是为了帮助初次接触或是需要DevExpress XtraReports报表的人群使用的,为了帮助更多的人不会像我这样浪 ...
- 独立博客网站FansUnion.cn操作2多年的经验和教训以及未来计划
今天,我把运营了2年的独立博客站点FansUnion给"归零"了. 2012年6月.我成功搭建了自己的博客站点FansUnion.cn,这是因为自己的不懈努力和时代发展成就的 ...
- 【高德API】如何利用MapKit开发全英文检索的iOS地图
原文:[高德API]如何利用MapKit开发全英文检索的iOS地图 制作全英文地图的展示并不困难,但是要制作全英文的数据检索列表,全英文的信息窗口,你就没办法了吧.告诉你,我有妙招!使用iOS自带的M ...
- Coreseek/sphinx全文检索的了解
Coreseek/sphinx全文检索的了解 概述: 全文检索是一种将文件里全部文本与检索项匹配的文字资料检索方法,全文检索是将存储于数据库中整本书.整篇文章中的随意内容信息查找出来的检索.它能够依据 ...
- VS2015前端工具:NPM和Web Essentials
VS2015前端工具:NPM和Web Essentials 1.写作背景 想在5月份前换个工作环境了,“检讨”一下自己混饭的技术水平和处世的人脉关系,觉得很不给力!为人方面,人各有志也就不纠结了,但本 ...
- asp.net [AjaxMethod]
AjaxPro.2.dll cs 代码 using AjaxPro; Utility.RegisterTypeForAjax(typeof(BOMdr_KT)); [Ajax.AjaxMethod() ...
- Oracle SqlPlus 方向键的方法和解决的退格键失效
SqlPlus中退格键和方向键的设置 在刚装好的Oracle中,我们使用SqlPlus会发现很的蹩脚,不仅退格键不好用,方向键也不行调出history.以下有几种解决方法. 1.能够使用ctrl+Ba ...
- IE6常见bug
1.IE6怪异解析之padding与border算入宽高 原因:未加文档声明造成非盒模型解析 解决方法:加入文档声明<!doctype html> 2.IE6在块元素.左右浮动.设定mar ...
- 2014年辛星PHP教程秋季版第一本即基础知识已经完工
因为本人还是蛮重视秋季版的,因此一開始就决定要把它做好,因此体系划分的比較具体,如今把它的第一本写作完成,在百度的下载点是:点我去百度 ,它的五十多个实例代码在百度的下载点是:点我下载源代码 ,当然, ...
- Spring之SpringMVC的MethodNameResolver(源码)分析
前言 在介绍SpringMVC 的Controller的具体实现中,我们讲到了MultiActionController.在获取处理请求对于的方法的时候我们用到了下面的代码,来自于MultiActi ...