动态代理是在运行时在内存中构建的一种类型,该类型实现了接口I,但是它将所有的方法调用都转发给类型A。
注意,上面我使用了“方法”调用的转发,由于,事件、属性都是方法的变体,所以,对接口中定义的所有元素的Call都可以被动态代理转发。那么,接口(I)中的方法与被代理者(Target)的方法如何匹配起来了?通常的方法是,进行“同名”匹配,比如ISimpleList接口的Add方法就自然匹配到List<>的Add方法。对于复杂的需求,可以定义一个方法名映射表来匹配不同名的方法。
由于,动态代理拥有这种为类型(Target)“换脸”的能力,所以,在很多场合可以使用它来优雅地解决一些以前难以处理的问题(通常,以前我们使用反射来解决这些麻烦),比如:
(1)“泛型参数类型是动态的”,使用动态代理解决这种问题不仅可以避免反射带来的性能损失,而且还可以获得强类型方法调用的好处。
(2)为一组类型“变脸”。比如,TextBox、RichTextBox、ListView等windows控件都有Clear方法,但是它们都没有实现一个统一的接口(比如,该接口中定义了Clear方法),所以当我要清空某个GroupBox中所有控件的内容时,无法用一种统一的方式调用,你不能这样做:
foreach (Control control in this.groupBox1.Controls)
{
control.Clear(); //Control不存在Clear方法,编译报错
}
{
control.Clear(); //Control不存在Clear方法,编译报错
}
但是有了动态代理之后,我们就可以为这些控件定义一个New Face:
public interface INewFace
{
void Clear();
}
{
void Clear();
}
然后优雅地这样调用:
foreach (Control control in this.groupBox1.Controls)
{
INewFace face = DynamicTypeEmitter.CreateDynamicProxy<INewFace>(control);
face.Clear();
}
{
INewFace face = DynamicTypeEmitter.CreateDynamicProxy<INewFace>(control);
face.Clear();
}
(3)使用动态代理除了转发调用外,可以为之注入预处理和后处理,这就是AOP的功能。Spring.NET的AOP实现即是通过动态代理做到的。
你可以继续挖掘使用动态代理的其它场合,发挥你的想象力,来展现动态代理的威力。
ESBasic.dll可以从当泛型的参数类型是动态的... 的文末下载。