循序渐进学习Castle.DynamicProxy AOP
2012-04-08 08:57
549 查看
http://www.it118.org/Specials/321869dd-98cb-431b-b6d2-82d973cd739d/0c2ad54b-387e-4761-8013-6d2007040051.htm
标签:Castle,AOP,Castle.DynamicProxy
Castle是一个框架,包含了AOP、IOC、ORM等多个方面,其中的Castle.DynamicProxy可以实现动态代理的功能,这个也是很多框架的基础。在IBatis.Net中就是使用了Castle.DynamicProxy来实现数据库连接等动态操作的。同时在NHibernet等其他框架中也使用到了这个技术。特点是实体不需要继承MarshalByRef、ContextBoundObject便可以实现代理类。基于透明代理的功能,可以实现对方法调用的拦截处理,例如NHibernate用它实现延迟加载DP的使用非常简单,内部没有使用反射,而是采用Emit、委托等方式生成代理类型,调用真实类的方法,性能方面也没有太多损失
项目地址:Castle Dynamic Proxy
一般情况下要有三个类:接口类,实现类,代理类。
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
Logger logger = generator.CreateClassProxy<Logger>(new TestInterceptor()); //泛型版
//Logger logger = generator.CreateClassProxy(typeof(Logger), new TestInterceptor()) as Logger; //非泛型版
logger.Write("love");
}
}
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Write("I ");
invocation.Proceed();
Console.Write(" you.");
}
}
public class Logger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
a.Logger是被代理的实体类,TestInterceptor是拦截器.
b.Logger中:public virtual
void Write(string message) 。好像必须是虚方法,如果不是虚方法,拦截不了。很是奇怪。
c.生成代理对象时,可以使用泛型版也可不使用泛型。建议使用泛型。
1.重构增加一个接口
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor());
logger.Write("love");
}
}
//拦截器
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Write("I ");
invocation.Proceed();
Console.Write(" you. ");
}
}
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger:ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
这次重构中增加了一个ILogger的接口。也是基于“接口隔离”,“依赖倒置”的设计原则。
2.重构切面前方法和切面后方法
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor());
logger.Write("love");
}
}
//拦截器
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
PreProceed(invocation);
invocation.Proceed();
PostProceed(invocation);
}
private void PreProceed(IInvocation invocation)
{
Console.Write("I ");
}
private void PostProceed(IInvocation invocation)
{
Console.Write(" you. ");
}
}
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger:ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
通常切面前和切面后方法都很复杂,通过重构让每个方法责任明确,单一。PreProceed:切面前处理函数。PostProceed:切面后处理方法。
3.使用StandardInterceptor再次重构切面前后方法。
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor());
logger.Write("love");
}
}
//拦截器
public class TestInterceptor : StandardInterceptor
{
protected override
void PreProceed(IInvocation invocation)
{
Console.Write("I ");
}
protected override
void PostProceed(IInvocation invocation)
{
Console.Write(" you. ");
}
}
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger:ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
无需赘述。
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor1(),
new TestInterceptor2() );
logger.Write("love");
}
}
#region 拦截器
//拦截器1
public class TestInterceptor1 : StandardInterceptor
{
protected override
void PreProceed(IInvocation invocation)
{
Console.Write("(张三 ");
}
protected override
void PostProceed(IInvocation invocation)
{
Console.Write(" 张四) ");
}
}
//拦截器2
public class TestInterceptor2 : StandardInterceptor
{
protected override
void PreProceed(IInvocation invocation)
{
Console.Write(" and 李三) ");
}
protected override
void PostProceed(IInvocation invocation)
{
Console.Write(" (李四 ");
}
}
#endregion
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger:ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
输出的结果为:(张三 和 李三 ) love (李四 和 张四)
多个拦截器之间以管道方式处理调用顺序:
上面示例使用的是class proxy,使用CreateClassProxy方法创建,该方法的某些版本要求有默认构造器,不使用默认构造器时则必须传入构造参数。代理对象为 class proxy类型时,被拦截的方法必须为virtual,non-virtual的方法无法实现拦截
interface proxy with target其实跟class proxy差不多,在创建代理对象时client指定接口,并且提供一个实现了该接口的对象作为真实对象,DP将创建这个接口的代理对象,对代理对象方法的调用经过拦截器处理之后,最终将调用真实对象相应的方法。与class proxy的不同之处在于,真实对象的方法不必是virtual类型也可以实现拦截
interface proxy without target比较特殊,创建代理时只需要指定一个接口就可以,DP自动根据接口构造一个实现的类,作为代理对象的类型,但这个代理类只能用于拦截目的,无法像class proxy一样在拦截器中调用真实对象的处理方法。比如在提供了多个拦截器时,最后一个拦截器的接口方法中不能调用 invocation.Proceed()方法,否则会抛异常(因为真实对象根本不存在,只有一个假的代理对象)
interface proxy with interface target与interface proxy with target基本类似,但他提供了一个更改被代理对象(真实对象)的机会,示例如下:
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
IStorageNode node = generator.CreateInterfaceProxyWithTargetInterface<IStorageNode>(
new StorageNode("master")
, new DualNodeInterceptor(new StorageNode("slave"))
, new CallingLogInterceptor());
node.Save("my message"); //应该调用master对象
node.IsDead = true;
node.Save("my message"); //应该调用slave对象
node.Save("my message");
//应该调用master对象
Console.ReadKey();
}
}
public interface IStorageNode
{
bool IsDead { get;
set; }
void Save(string message);
}
public class StorageNode : IStorageNode
{
private string _name;
public StorageNode(string name)
{
this._name = name;
}
public bool IsDead {
get; set; }
public void Save(string message)
{
Console.WriteLine(string.Format("\"{0}\" was saved to {1}", message,
this._name));
}
}
public class DualNodeInterceptor : IInterceptor
{
private IStorageNode _slave;
public DualNodeInterceptor(IStorageNode slave)
{
this._slave = slave;
}
public void Intercept(IInvocation invocation)
{
IStorageNode master = invocation.InvocationTarget
as IStorageNode;
if (master.IsDead)
{
IChangeProxyTarget cpt = invocation as IChangeProxyTarget;
//将被代理对象master更换为slave
cpt.ChangeProxyTarget(this._slave);
//测试中恢复master的状态,以便看到随后的调用仍然使用master这一效果
master.IsDead = false;
}
invocation.Proceed();
}
}
public class CallingLogInterceptor : StandardInterceptor
{
private int _indent = 0;
protected override
void PreProceed(IInvocation invocation)
{
if (this._indent > 0)
Console.Write(" ".PadRight(this._indent * 4,
' '));
this._indent++;
Console.Write("Intercepting: " + invocation.Method.Name +
"(");
if (invocation.Arguments != null && invocation.Arguments.Length > 0)
for (int i = 0; i < invocation.Arguments.Length; i++)
{
if (i != 0) Console.Write(", ");
Console.Write(invocation.Arguments[i] == null
? "null"
: invocation.Arguments[i].GetType() == typeof(string)
? "\"" + invocation.Arguments[i].ToString() +
"\""
: invocation.Arguments[i].ToString());
}
Console.WriteLine(")");
}
protected override
void PostProceed(IInvocation invocation)
{
this._indent--;
}
}
}
只有在interface proxy with interface target的情况下IInterceptor的接口参数IInvocation对象才实现了IChangeProxyTarget接口
IChangeProxyTarget的ChangeInvocationTarget方法将本次调用的被代理对象替换掉,而ChangeProxyTarget方法则永久的将被代理对象替换,但不包括本次调用
使用DP我们可以在C#中实现mixin,示例如下:
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
var options = new ProxyGenerationOptions();
options.AddMixinInstance(new ClassA());
ClassB objB = generator.CreateClassProxy<ClassB>(options,
new CallingLogInterceptor());
objB.ActionB();
InterfaceA objA = objB as InterfaceA;
objA.ActionA();
Console.ReadKey();
}
}
public interface InterfaceA
{
void ActionA();
}
public class ClassA : InterfaceA
{
public void ActionA()
{
Console.WriteLine("I'm from ClassA");
}
}
public class ClassB
{
public virtual
void ActionB()
{
Console.WriteLine("I'm from ClassB");
}
}
public class CallingLogInterceptor : StandardInterceptor
{
private int _indent = 0;
protected override
void PreProceed(IInvocation invocation)
{
if (this._indent > 0)
Console.Write(" ".PadRight(this._indent * 4,
' '));
this._indent++;
Console.Write("Intercepting: " + invocation.Method.Name +
"(");
if (invocation.Arguments !=
null && invocation.Arguments.Length > 0)
for (int i = 0; i < invocation.Arguments.Length; i++)
{
if (i != 0) Console.Write(", ");
Console.Write(invocation.Arguments[i] ==
null
? "null"
: invocation.Arguments[i].GetType() ==
typeof(string)
? "\"" + invocation.Arguments[i].ToString() +
"\""
: invocation.Arguments[i].ToString());
}
Console.WriteLine(")");
}
protected override
void PostProceed(IInvocation invocation)
{
this._indent--;
}
}
}
可以看到代理对象同时具备了ClassA和ClassB的行为
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
String path = AppDomain.CurrentDomain.BaseDirectory;
ModuleScope scope = new ModuleScope(true,
"Invocation", path + "\\Invocation.dll",
"Proxy", path + "\\Proxy.dll");
DefaultProxyBuilder builder = new DefaultProxyBuilder(scope);
ProxyGenerator generator = new ProxyGenerator(builder);
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor());
logger.Write("love");
scope.SaveAssembly(true);
//加这句话可以将动态生成的Invocation类保存到本地硬盘
scope.SaveAssembly(false);
//加这句话可以将动态生成的Proxy类保存到本地硬盘
Console.ReadKey();
}
}
//拦截器
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Write("I ");
invocation.Proceed();
Console.Write(" you. ");
}
}
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger : ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
可以用reflector查看生成的dll,大致了解代理对象是如何工作的启动时,可以使用scope.LoadAssemblyIntoCache(assembly);将生成的代理类型加载到内存中,其中assembly需要我们手动加载
标签:Castle,AOP,Castle.DynamicProxy
Castle是一个框架,包含了AOP、IOC、ORM等多个方面,其中的Castle.DynamicProxy可以实现动态代理的功能,这个也是很多框架的基础。在IBatis.Net中就是使用了Castle.DynamicProxy来实现数据库连接等动态操作的。同时在NHibernet等其他框架中也使用到了这个技术。特点是实体不需要继承MarshalByRef、ContextBoundObject便可以实现代理类。基于透明代理的功能,可以实现对方法调用的拦截处理,例如NHibernate用它实现延迟加载DP的使用非常简单,内部没有使用反射,而是采用Emit、委托等方式生成代理类型,调用真实类的方法,性能方面也没有太多损失
项目地址:Castle Dynamic Proxy
一般情况下要有三个类:接口类,实现类,代理类。
一.Castle.DynamicProxy 实现的最简单的AOP
using System;using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
Logger logger = generator.CreateClassProxy<Logger>(new TestInterceptor()); //泛型版
//Logger logger = generator.CreateClassProxy(typeof(Logger), new TestInterceptor()) as Logger; //非泛型版
logger.Write("love");
}
}
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Write("I ");
invocation.Proceed();
Console.Write(" you.");
}
}
public class Logger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
a.Logger是被代理的实体类,TestInterceptor是拦截器.
b.Logger中:public virtual
void Write(string message) 。好像必须是虚方法,如果不是虚方法,拦截不了。很是奇怪。
c.生成代理对象时,可以使用泛型版也可不使用泛型。建议使用泛型。
1.重构增加一个接口
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor());
logger.Write("love");
}
}
//拦截器
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Write("I ");
invocation.Proceed();
Console.Write(" you. ");
}
}
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger:ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
这次重构中增加了一个ILogger的接口。也是基于“接口隔离”,“依赖倒置”的设计原则。
2.重构切面前方法和切面后方法
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor());
logger.Write("love");
}
}
//拦截器
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
PreProceed(invocation);
invocation.Proceed();
PostProceed(invocation);
}
private void PreProceed(IInvocation invocation)
{
Console.Write("I ");
}
private void PostProceed(IInvocation invocation)
{
Console.Write(" you. ");
}
}
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger:ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
通常切面前和切面后方法都很复杂,通过重构让每个方法责任明确,单一。PreProceed:切面前处理函数。PostProceed:切面后处理方法。
3.使用StandardInterceptor再次重构切面前后方法。
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor());
logger.Write("love");
}
}
//拦截器
public class TestInterceptor : StandardInterceptor
{
protected override
void PreProceed(IInvocation invocation)
{
Console.Write("I ");
}
protected override
void PostProceed(IInvocation invocation)
{
Console.Write(" you. ");
}
}
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger:ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
无需赘述。
二、创建代理对象时可以指定多个拦截器
using System;using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor1(),
new TestInterceptor2() );
logger.Write("love");
}
}
#region 拦截器
//拦截器1
public class TestInterceptor1 : StandardInterceptor
{
protected override
void PreProceed(IInvocation invocation)
{
Console.Write("(张三 ");
}
protected override
void PostProceed(IInvocation invocation)
{
Console.Write(" 张四) ");
}
}
//拦截器2
public class TestInterceptor2 : StandardInterceptor
{
protected override
void PreProceed(IInvocation invocation)
{
Console.Write(" and 李三) ");
}
protected override
void PostProceed(IInvocation invocation)
{
Console.Write(" (李四 ");
}
}
#endregion
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger:ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
输出的结果为:(张三 和 李三 ) love (李四 和 张四)
多个拦截器之间以管道方式处理调用顺序:
三、代理类型 Proxy Types
代理类型有class proxy、interface proxy with target、interface proxy without target、interface proxy with interface target几种上面示例使用的是class proxy,使用CreateClassProxy方法创建,该方法的某些版本要求有默认构造器,不使用默认构造器时则必须传入构造参数。代理对象为 class proxy类型时,被拦截的方法必须为virtual,non-virtual的方法无法实现拦截
interface proxy with target其实跟class proxy差不多,在创建代理对象时client指定接口,并且提供一个实现了该接口的对象作为真实对象,DP将创建这个接口的代理对象,对代理对象方法的调用经过拦截器处理之后,最终将调用真实对象相应的方法。与class proxy的不同之处在于,真实对象的方法不必是virtual类型也可以实现拦截
interface proxy without target比较特殊,创建代理时只需要指定一个接口就可以,DP自动根据接口构造一个实现的类,作为代理对象的类型,但这个代理类只能用于拦截目的,无法像class proxy一样在拦截器中调用真实对象的处理方法。比如在提供了多个拦截器时,最后一个拦截器的接口方法中不能调用 invocation.Proceed()方法,否则会抛异常(因为真实对象根本不存在,只有一个假的代理对象)
interface proxy with interface target与interface proxy with target基本类似,但他提供了一个更改被代理对象(真实对象)的机会,示例如下:
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
IStorageNode node = generator.CreateInterfaceProxyWithTargetInterface<IStorageNode>(
new StorageNode("master")
, new DualNodeInterceptor(new StorageNode("slave"))
, new CallingLogInterceptor());
node.Save("my message"); //应该调用master对象
node.IsDead = true;
node.Save("my message"); //应该调用slave对象
node.Save("my message");
//应该调用master对象
Console.ReadKey();
}
}
public interface IStorageNode
{
bool IsDead { get;
set; }
void Save(string message);
}
public class StorageNode : IStorageNode
{
private string _name;
public StorageNode(string name)
{
this._name = name;
}
public bool IsDead {
get; set; }
public void Save(string message)
{
Console.WriteLine(string.Format("\"{0}\" was saved to {1}", message,
this._name));
}
}
public class DualNodeInterceptor : IInterceptor
{
private IStorageNode _slave;
public DualNodeInterceptor(IStorageNode slave)
{
this._slave = slave;
}
public void Intercept(IInvocation invocation)
{
IStorageNode master = invocation.InvocationTarget
as IStorageNode;
if (master.IsDead)
{
IChangeProxyTarget cpt = invocation as IChangeProxyTarget;
//将被代理对象master更换为slave
cpt.ChangeProxyTarget(this._slave);
//测试中恢复master的状态,以便看到随后的调用仍然使用master这一效果
master.IsDead = false;
}
invocation.Proceed();
}
}
public class CallingLogInterceptor : StandardInterceptor
{
private int _indent = 0;
protected override
void PreProceed(IInvocation invocation)
{
if (this._indent > 0)
Console.Write(" ".PadRight(this._indent * 4,
' '));
this._indent++;
Console.Write("Intercepting: " + invocation.Method.Name +
"(");
if (invocation.Arguments != null && invocation.Arguments.Length > 0)
for (int i = 0; i < invocation.Arguments.Length; i++)
{
if (i != 0) Console.Write(", ");
Console.Write(invocation.Arguments[i] == null
? "null"
: invocation.Arguments[i].GetType() == typeof(string)
? "\"" + invocation.Arguments[i].ToString() +
"\""
: invocation.Arguments[i].ToString());
}
Console.WriteLine(")");
}
protected override
void PostProceed(IInvocation invocation)
{
this._indent--;
}
}
}
只有在interface proxy with interface target的情况下IInterceptor的接口参数IInvocation对象才实现了IChangeProxyTarget接口
IChangeProxyTarget的ChangeInvocationTarget方法将本次调用的被代理对象替换掉,而ChangeProxyTarget方法则永久的将被代理对象替换,但不包括本次调用
四、Mixins
要准确的将mixin翻译为中文比较难找到一个合适的词汇,他的大意是指在运行期使用“合并”的方式修改对象的行为。比如对象obj的类型为A,在运行时将类型B的所有属性和方法“混入”到对象obj上,使得对象obj同时具备类型A和B的属性和行为,就好像obj同时继承了A和B。在动态语言中比较容易实现这个效果,比如python本身支持多继承,还可以通过__bases__动态修改基类,所以python中使用mixin技术是非常简单的,包括 javascript也很容易实现这个效果。关于mixin概念的详细说明参考wikipedia使用DP我们可以在C#中实现mixin,示例如下:
using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
ProxyGenerator generator = new ProxyGenerator();
var options = new ProxyGenerationOptions();
options.AddMixinInstance(new ClassA());
ClassB objB = generator.CreateClassProxy<ClassB>(options,
new CallingLogInterceptor());
objB.ActionB();
InterfaceA objA = objB as InterfaceA;
objA.ActionA();
Console.ReadKey();
}
}
public interface InterfaceA
{
void ActionA();
}
public class ClassA : InterfaceA
{
public void ActionA()
{
Console.WriteLine("I'm from ClassA");
}
}
public class ClassB
{
public virtual
void ActionB()
{
Console.WriteLine("I'm from ClassB");
}
}
public class CallingLogInterceptor : StandardInterceptor
{
private int _indent = 0;
protected override
void PreProceed(IInvocation invocation)
{
if (this._indent > 0)
Console.Write(" ".PadRight(this._indent * 4,
' '));
this._indent++;
Console.Write("Intercepting: " + invocation.Method.Name +
"(");
if (invocation.Arguments !=
null && invocation.Arguments.Length > 0)
for (int i = 0; i < invocation.Arguments.Length; i++)
{
if (i != 0) Console.Write(", ");
Console.Write(invocation.Arguments[i] ==
null
? "null"
: invocation.Arguments[i].GetType() ==
typeof(string)
? "\"" + invocation.Arguments[i].ToString() +
"\""
: invocation.Arguments[i].ToString());
}
Console.WriteLine(")");
}
protected override
void PostProceed(IInvocation invocation)
{
this._indent--;
}
}
}
可以看到代理对象同时具备了ClassA和ClassB的行为
五、导出、生成代理类型
Castle Dynamic Proxy允许我们将运行时生成的代理类型生成dll文件存到磁盘上,下次启动时通过加载这个dll文件可以避免动态生成代理类型using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;
namespace DynamicProxyExample
{
class Program
{
static void Main(string[] args)
{
String path = AppDomain.CurrentDomain.BaseDirectory;
ModuleScope scope = new ModuleScope(true,
"Invocation", path + "\\Invocation.dll",
"Proxy", path + "\\Proxy.dll");
DefaultProxyBuilder builder = new DefaultProxyBuilder(scope);
ProxyGenerator generator = new ProxyGenerator(builder);
ILogger logger = generator.CreateClassProxy<Logger>(new TestInterceptor());
logger.Write("love");
scope.SaveAssembly(true);
//加这句话可以将动态生成的Invocation类保存到本地硬盘
scope.SaveAssembly(false);
//加这句话可以将动态生成的Proxy类保存到本地硬盘
Console.ReadKey();
}
}
//拦截器
public class TestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Write("I ");
invocation.Proceed();
Console.Write(" you. ");
}
}
//接口
public interface ILogger
{
void Write(string message);
}
//实现类
public class Logger : ILogger
{
public virtual
void Write(string message)
{
Console.Write(message);
}
}
}
可以用reflector查看生成的dll,大致了解代理对象是如何工作的启动时,可以使用scope.LoadAssemblyIntoCache(assembly);将生成的代理类型加载到内存中,其中assembly需要我们手动加载
相关文章推荐
- 框架学习与探究之AOP--Castle DynamicProxy
- 【框架学习与探究之AOP--Castle DynamicProxy】
- castle.dynamicProxy学习笔记
- AOP:PostSharp和Castle DynamicProxy
- Autofac整合Castle.DynamicProxy实现AOP
- ITCAST视频-Spring学习笔记(使用JDK中的Proxy技术实现AOP功能)
- Castle.DynamicProxy Part 1: ClassProxy
- Castle 系列: Castle DynamicProxy动态生成透明代理类型
- IBatis.Net学习笔记(六):Castle.DynamicProxy的使用
- Castle.DynamicProxy实现WCF接口服务端模拟
- AOP源码分析-CglibAopProxy DynamicAdvisedInterceptor
- IBatis.Net学习笔记十一:Castle.DynamicProxy的使用 (转)
- Spring学习笔记 —— AOP(面向切面编程) 之使用ProxyFactoryBean实现AOP
- Castle Dynamic Proxy - 2.2
- Castle.DynamicProxy的二次开发
- JdkDynamicAopProxy源码
- 【Spring学习19】作用域:使用代理<aop:scoped-proxy/>
- Dynamic CRM 2013学习笔记(三十)Linq使用报错 A proxy type with the name account has been defined by another assembly
- IBatis.Net学习笔记(六):Castle.DynamicProxy的使用
- Castle DynamicProxy creation出现COMException(0x800703fa)错误的解决方案