动态方法与动态代理(下篇)
2011-07-10 12:11 熬夜的虫子 阅读(526) 评论(0) 编辑 收藏 举报动态代理:
代理模式和装饰模式的区别:
装饰模式:在不改变接口的前提下,动态扩展对象的功能
代理模式:在不改变接口的前提下,控制对象的访问
代理类和被代理对象是has-a关系,一般没有is-a关系,除非代理类直接继承被代理类,重写被代理类的方法
动态代理是指通过动态代码技术在运行时生成具体类的代理,目的是在执行具体类的操作之前或之后运行特定的逻辑
动态代理既可以代理类也可以代理接口,代理类时,被代理的类不能为Sealed,并且其中属性和方法都必须为Virtual,而代理接口时则无约束条件
•Demo:动态生成接口的代理
View Code
1 public interface ICalculate
2 {
3 void Add(int a, int b);
4 }
5
6 public class A : ICalculate
7 {
8 #region ICalculate 成员
9
10 public void Add(int a, int b)
11 {
12 Console.WriteLine(a + b);
13 }
14
15 #endregion
16 }
17
18 public class B : ICalculate
19 {
20 ICalculate _inst;
21
22 public B(ICalculate o)
23 {
24 _inst = o;
25 }
26
27 #region ICalculate 成员
28
29 public void Add(int a, int b)
30 {
31 Console.WriteLine("Before...");
32 _inst.Add(a, b);
33 Console.WriteLine("After...");
34 }
35
36 #endregion
37 }
38
39 class Program
40 {
41 static void Main(string[] args)
42 {
43 Type proxyType;//代理类型
44
45 #region Emit Class
46
47 AssemblyName assemblyName = new AssemblyName("DynamicAssemblyExample");
48 AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
49 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll");
50
51 TypeBuilder typeBuilder = moduleBuilder.DefineType("DynamicAssemblyExample.Calculate", TypeAttributes.Public | TypeAttributes.Class
52 , typeof(object), new Type[] { typeof(ICalculate) });
53
54 FieldBuilder instanceField = typeBuilder.DefineField("_instance", typeof(ICalculate), FieldAttributes.Private);
55
56 ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(ICalculate) });
57
58 ILGenerator ilGenConstructor = constructorBuilder.GetILGenerator();
59 ilGenConstructor.Emit(OpCodes.Ldarg_0);
60 ilGenConstructor.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); //base.ctor()
61 ilGenConstructor.Emit(OpCodes.Ldarg_0);
62 ilGenConstructor.Emit(OpCodes.Ldarg_1);
63 ilGenConstructor.Emit(OpCodes.Stfld, instanceField);
64 ilGenConstructor.Emit(OpCodes.Ret);
65
66 MethodInfo addMethodInfo = typeof(ICalculate).GetMethod("Add");
67
68 MethodAttributes methodAttr = addMethodInfo.Attributes & ~(MethodAttributes.Abstract);
69
70 List<Type> paramTypes = new List<Type>();
71
72 foreach (ParameterInfo pInfo in addMethodInfo.GetParameters())
73 {
74 paramTypes.Add(pInfo.ParameterType);
75 }
76
77 MethodBuilder addMethod = typeBuilder.DefineMethod(addMethodInfo.Name, methodAttr,
78 CallingConventions.Standard, addMethodInfo.ReturnType, paramTypes.ToArray());
79
80 //writeline call
81 MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
82
83 ILGenerator ilGenAddMethod = addMethod.GetILGenerator();
84
85
86 ilGenAddMethod.Emit(OpCodes.Ldstr, "Before...");
87 ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
88
89 //每个实例方法都默认包含一个隐藏的参数,即第0个参数,它对应的是this指针,但静态方法没有隐藏的第0个参数
90 ilGenAddMethod.Emit(OpCodes.Ldarg_0);
91 ilGenAddMethod.Emit(OpCodes.Ldfld, instanceField);
92
93
94 ilGenAddMethod.Emit(OpCodes.Ldarg_1);//a
95 ilGenAddMethod.Emit(OpCodes.Ldarg_2);//b
96 ilGenAddMethod.Emit(OpCodes.Callvirt, typeof(ICalculate).GetMethod("Add"));//a+b
97
98 ilGenAddMethod.Emit(OpCodes.Ldstr, "After...");
99 ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
100
101 /*
102 * Console.WriteLine(this.GetType().FullName);
103 */
104 ilGenAddMethod.DeclareLocal(typeof(int));
105 ilGenAddMethod.Emit(OpCodes.Ldarg_0);
106 ilGenAddMethod.Emit(OpCodes.Callvirt, typeof(object).GetMethod("GetType"));
107 ilGenAddMethod.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("get_FullName"));
108 ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
109
110
111 ilGenAddMethod.Emit(OpCodes.Ret);
112
113 proxyType = typeBuilder.CreateType();
114
115 assemblyBuilder.Save("DynamicAssemblyExample.dll");
116 #endregion
117
118 ICalculate proxyImp = (ICalculate)proxyType.GetConstructor(new Type[] { typeof(ICalculate) })
119 .Invoke(new object[] { new A() });
120
121 proxyImp.Add(10, 20);
122 }
123 }
2 {
3 void Add(int a, int b);
4 }
5
6 public class A : ICalculate
7 {
8 #region ICalculate 成员
9
10 public void Add(int a, int b)
11 {
12 Console.WriteLine(a + b);
13 }
14
15 #endregion
16 }
17
18 public class B : ICalculate
19 {
20 ICalculate _inst;
21
22 public B(ICalculate o)
23 {
24 _inst = o;
25 }
26
27 #region ICalculate 成员
28
29 public void Add(int a, int b)
30 {
31 Console.WriteLine("Before...");
32 _inst.Add(a, b);
33 Console.WriteLine("After...");
34 }
35
36 #endregion
37 }
38
39 class Program
40 {
41 static void Main(string[] args)
42 {
43 Type proxyType;//代理类型
44
45 #region Emit Class
46
47 AssemblyName assemblyName = new AssemblyName("DynamicAssemblyExample");
48 AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
49 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll");
50
51 TypeBuilder typeBuilder = moduleBuilder.DefineType("DynamicAssemblyExample.Calculate", TypeAttributes.Public | TypeAttributes.Class
52 , typeof(object), new Type[] { typeof(ICalculate) });
53
54 FieldBuilder instanceField = typeBuilder.DefineField("_instance", typeof(ICalculate), FieldAttributes.Private);
55
56 ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(ICalculate) });
57
58 ILGenerator ilGenConstructor = constructorBuilder.GetILGenerator();
59 ilGenConstructor.Emit(OpCodes.Ldarg_0);
60 ilGenConstructor.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); //base.ctor()
61 ilGenConstructor.Emit(OpCodes.Ldarg_0);
62 ilGenConstructor.Emit(OpCodes.Ldarg_1);
63 ilGenConstructor.Emit(OpCodes.Stfld, instanceField);
64 ilGenConstructor.Emit(OpCodes.Ret);
65
66 MethodInfo addMethodInfo = typeof(ICalculate).GetMethod("Add");
67
68 MethodAttributes methodAttr = addMethodInfo.Attributes & ~(MethodAttributes.Abstract);
69
70 List<Type> paramTypes = new List<Type>();
71
72 foreach (ParameterInfo pInfo in addMethodInfo.GetParameters())
73 {
74 paramTypes.Add(pInfo.ParameterType);
75 }
76
77 MethodBuilder addMethod = typeBuilder.DefineMethod(addMethodInfo.Name, methodAttr,
78 CallingConventions.Standard, addMethodInfo.ReturnType, paramTypes.ToArray());
79
80 //writeline call
81 MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
82
83 ILGenerator ilGenAddMethod = addMethod.GetILGenerator();
84
85
86 ilGenAddMethod.Emit(OpCodes.Ldstr, "Before...");
87 ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
88
89 //每个实例方法都默认包含一个隐藏的参数,即第0个参数,它对应的是this指针,但静态方法没有隐藏的第0个参数
90 ilGenAddMethod.Emit(OpCodes.Ldarg_0);
91 ilGenAddMethod.Emit(OpCodes.Ldfld, instanceField);
92
93
94 ilGenAddMethod.Emit(OpCodes.Ldarg_1);//a
95 ilGenAddMethod.Emit(OpCodes.Ldarg_2);//b
96 ilGenAddMethod.Emit(OpCodes.Callvirt, typeof(ICalculate).GetMethod("Add"));//a+b
97
98 ilGenAddMethod.Emit(OpCodes.Ldstr, "After...");
99 ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
100
101 /*
102 * Console.WriteLine(this.GetType().FullName);
103 */
104 ilGenAddMethod.DeclareLocal(typeof(int));
105 ilGenAddMethod.Emit(OpCodes.Ldarg_0);
106 ilGenAddMethod.Emit(OpCodes.Callvirt, typeof(object).GetMethod("GetType"));
107 ilGenAddMethod.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("get_FullName"));
108 ilGenAddMethod.Emit(OpCodes.Call, writeLineMethod);
109
110
111 ilGenAddMethod.Emit(OpCodes.Ret);
112
113 proxyType = typeBuilder.CreateType();
114
115 assemblyBuilder.Save("DynamicAssemblyExample.dll");
116 #endregion
117
118 ICalculate proxyImp = (ICalculate)proxyType.GetConstructor(new Type[] { typeof(ICalculate) })
119 .Invoke(new object[] { new A() });
120
121 proxyImp.Add(10, 20);
122 }
123 }
AOP的概念
•Aspect Oriented Programming
•AOP是OOP的延续,意思是面向切面编程
•切面是指整体中的某个行为(功能)部分
•目标:将与主逻辑无紧密关系的行为,从业务逻辑代码中分离出来
•优点:当改变某个行为时,不会影响到业务逻辑,并且使代码进一步解耦
•常用于日志记录,性能统计,安全控制,事务处理,异常处理等等
AOP的工作原理
•AOP的关键是拦截正常的方法调用,即将需要额外附加的功能透明的“织入( Weave)”到这些方法中
•所谓“织入”简单的讲就是指将附件功能和目标的原有功能融合在一起,AOP像一台织布机,将两者天衣无缝的编织起来,织入是透明的
•在.Net中,AOP的织入方式有两种:
静态织入:在编译阶段将附加逻辑写入代码中
动态织入:在运行阶段将附加逻辑写入代码中
•静态织入:一般都需要扩展编译器的功能,优点是代码执行的效率高,缺点是实现者需要对虚拟机有很深的了解,而且修改代码之后都需要重新编译,目前,最著名的产品是:PostSharp
•动态织入:不需要扩展编译器的功能,优点是在运行时自动生成代码,缺点是执行效率不高,需要额外的开销,目前,运用动态织入方法的产品较多,Castle.DynamicProxy是其中的经典之一
动态织入的实现技术就是动态代理,由于静态织入存在局限性,一般来说,AOP框架实现方式首选动态织入,因此,AOP可以看作是动态代理发展的产物
•Demo:AOP实践Castle.DynamicProxy
这是一个轻量级的,能为一个或多个接口或具体类创建动态代理的类库,或者称之为AOP类库内部机制是使用反射发出动态织入
拦截器( Interceptor)是其中的重要概念,用于截获方法的调用,增加新的逻辑,自定义拦截器必须实现IInterceptor接口或者继承内置的标准拦截器类StandardInterceptor拦截器对方法和属性都有效
典型应用:
参数检验
延迟加载(Lazy Loading)
典型代表:
NHibernate
View Code
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 DemoClassInterceptorTest.DoTest();
6
7 //DemoInterfaceInterceptorTest.DoTest();
8 }
9 }
10 public interface IDemoInterface
11 {
12 void Add(int a, int b);
13 }
14
15 public class DemoInterfaceClass : IDemoInterface
16 {
17 #region DemoInterface 成员
18
19 public void Add(int a, int b)
20 {
21 Console.WriteLine(a + b);
22 }
23
24 #endregion
25 }
26
27 public class DemoInterfaceInterceptor : StandardInterceptor
28 {
29 protected override void PreProceed(IInvocation invocation)
30 {
31 Console.WriteLine("PreProceed:{0}", invocation.Method.ToString());
32 }
33
34 protected override void PostProceed(IInvocation invocation)
35 {
36 Console.WriteLine("PostProceed:{0}", invocation.Method.ToString());
37 }
38
39 protected override void PerformProceed(IInvocation invocation)
40 {
41 base.PerformProceed(invocation);
42 }
43 }
44
45 public class DemoInterfaceInterceptorTest
46 {
47 public static void DoTest()
48 {
49 DemoInterfaceClass realObj = new DemoInterfaceClass();
50
51 DemoInterfaceInterceptor interceptor = new DemoInterfaceInterceptor();
52
53 ProxyGenerator generator = new ProxyGenerator();
54 IDemoInterface proxy=generator.CreateInterfaceProxyWithTargetInterface<IDemoInterface>(realObj, interceptor);
55 proxy.Add(10, 50);
56 }
57 }
2 {
3 static void Main(string[] args)
4 {
5 DemoClassInterceptorTest.DoTest();
6
7 //DemoInterfaceInterceptorTest.DoTest();
8 }
9 }
10 public interface IDemoInterface
11 {
12 void Add(int a, int b);
13 }
14
15 public class DemoInterfaceClass : IDemoInterface
16 {
17 #region DemoInterface 成员
18
19 public void Add(int a, int b)
20 {
21 Console.WriteLine(a + b);
22 }
23
24 #endregion
25 }
26
27 public class DemoInterfaceInterceptor : StandardInterceptor
28 {
29 protected override void PreProceed(IInvocation invocation)
30 {
31 Console.WriteLine("PreProceed:{0}", invocation.Method.ToString());
32 }
33
34 protected override void PostProceed(IInvocation invocation)
35 {
36 Console.WriteLine("PostProceed:{0}", invocation.Method.ToString());
37 }
38
39 protected override void PerformProceed(IInvocation invocation)
40 {
41 base.PerformProceed(invocation);
42 }
43 }
44
45 public class DemoInterfaceInterceptorTest
46 {
47 public static void DoTest()
48 {
49 DemoInterfaceClass realObj = new DemoInterfaceClass();
50
51 DemoInterfaceInterceptor interceptor = new DemoInterfaceInterceptor();
52
53 ProxyGenerator generator = new ProxyGenerator();
54 IDemoInterface proxy=generator.CreateInterfaceProxyWithTargetInterface<IDemoInterface>(realObj, interceptor);
55 proxy.Add(10, 50);
56 }
57 }
View Code
1 public class DemoClass
2 {
3
4 string _text;
5 public virtual string Text
6 {
7 get
8 {
9 return _text;
10 }
11 set
12 {
13 _text = value;
14 }
15 }
16
17 public virtual void Add(int a, int b)
18 {
19 Console.WriteLine(a + b);
20 }
21 }
22
23 class DemoClassInterceptor : IInterceptor
24 {
25 #region IInterceptor 成员
26
27 /// <summary>
28 /// Intercepts the specified invocation.
29 /// </summary>
30 /// <param name="invocation">The invocation.</param>
31 public void Intercept(IInvocation invocation)
32 {
33 PreProceed(invocation);
34 invocation.Proceed();
35 PostProceed(invocation);
36 }
37
38 #endregion
39
40 public void PreProceed(IInvocation invocation)
41 {
42 Console.WriteLine("PreProceed 1 代理了:{0}", invocation.Method.ToString());
43 }
44
45 public void PostProceed(IInvocation invocation)
46 {
47 Console.WriteLine("PostProceed 1 代理了:{0}", invocation.Method.ToString());
48 }
49 }
50
51 class DemoClassInterceptor2 : IInterceptor
52 {
53 #region IInterceptor 成员
54
55 /// <summary>
56 /// Intercepts the specified invocation.
57 /// </summary>
58 /// <param name="invocation">The invocation.</param>
59 public void Intercept(IInvocation invocation)
60 {
61 PreProceed(invocation);
62 invocation.Proceed();
63 PostProceed(invocation);
64 }
65
66 #endregion
67
68 public void PreProceed(IInvocation invocation)
69 {
70 Console.WriteLine("PreProceed 2 代理了:{0}", invocation.Method.ToString());
71 }
72
73 public void PostProceed(IInvocation invocation)
74 {
75 Console.WriteLine("PostProceed 2 代理了:{0}", invocation.Method.ToString());
76 }
77 }
78
79 class DemoClassInterceptorTest
80 {
81 public static void DoTest()
82 {
83 ProxyGenerator generator = new ProxyGenerator();
84 DemoClassInterceptor interceptor = new DemoClassInterceptor();
85 DemoClassInterceptor2 interceptor2 = new DemoClassInterceptor2();
86 DemoClass obj = generator.CreateClassProxy<DemoClass>(interceptor, interceptor2);
87 obj.Text = "test";
88 obj.Add(10, 20);
89 }
90 }
2 {
3
4 string _text;
5 public virtual string Text
6 {
7 get
8 {
9 return _text;
10 }
11 set
12 {
13 _text = value;
14 }
15 }
16
17 public virtual void Add(int a, int b)
18 {
19 Console.WriteLine(a + b);
20 }
21 }
22
23 class DemoClassInterceptor : IInterceptor
24 {
25 #region IInterceptor 成员
26
27 /// <summary>
28 /// Intercepts the specified invocation.
29 /// </summary>
30 /// <param name="invocation">The invocation.</param>
31 public void Intercept(IInvocation invocation)
32 {
33 PreProceed(invocation);
34 invocation.Proceed();
35 PostProceed(invocation);
36 }
37
38 #endregion
39
40 public void PreProceed(IInvocation invocation)
41 {
42 Console.WriteLine("PreProceed 1 代理了:{0}", invocation.Method.ToString());
43 }
44
45 public void PostProceed(IInvocation invocation)
46 {
47 Console.WriteLine("PostProceed 1 代理了:{0}", invocation.Method.ToString());
48 }
49 }
50
51 class DemoClassInterceptor2 : IInterceptor
52 {
53 #region IInterceptor 成员
54
55 /// <summary>
56 /// Intercepts the specified invocation.
57 /// </summary>
58 /// <param name="invocation">The invocation.</param>
59 public void Intercept(IInvocation invocation)
60 {
61 PreProceed(invocation);
62 invocation.Proceed();
63 PostProceed(invocation);
64 }
65
66 #endregion
67
68 public void PreProceed(IInvocation invocation)
69 {
70 Console.WriteLine("PreProceed 2 代理了:{0}", invocation.Method.ToString());
71 }
72
73 public void PostProceed(IInvocation invocation)
74 {
75 Console.WriteLine("PostProceed 2 代理了:{0}", invocation.Method.ToString());
76 }
77 }
78
79 class DemoClassInterceptorTest
80 {
81 public static void DoTest()
82 {
83 ProxyGenerator generator = new ProxyGenerator();
84 DemoClassInterceptor interceptor = new DemoClassInterceptor();
85 DemoClassInterceptor2 interceptor2 = new DemoClassInterceptor2();
86 DemoClass obj = generator.CreateClassProxy<DemoClass>(interceptor, interceptor2);
87 obj.Text = "test";
88 obj.Add(10, 20);
89 }
90 }
原创作品允许转载,转载时请务必以超链接形式标明文章原始出处以及作者信息。 作者:熬夜的虫子 点击查看:博文索引 |
|