.net的动态代理
来源:互联网 发布:mac带圈圈的数字怎么打 编辑:程序博客网 时间:2024/05/16 17:22
=============咯咯咯=============
动态代理的工作模式:
一般我们获取一个类型的实例都是通过 new 关键字,例如 var c = new Class1(); 通过动态代理的话,我们获取一个实例是通过代理方法获取的,generator.CreateClassProxy(type, interceptor); 其中Type是要代理的类型,也就是Class1(); interceptor则是实际执行代理的拦截器。
为什么我们要这么麻烦的使用代理而不是直接new实例?
简单的说,例如我Class1与Class2都有自己的方法,我现在想给这两给类的每个方法都添加一个日志操作,如果不通过代理我们怎么做呢?每个函数开始增加一句Log.Enter();结束的时候增加一个Log.Exit(); 如果涉及到TryCatch这类的,会更麻烦。通过动态代理,我们可以增加一个拦截器,拦截器中,可以先执行Log.Enter();然后执行实际操作,最后在执行Log.Exit(); 这样我们就不需要去修改 Class1与Class2两个类。
在这个项目里,动态代理有两个功能,一个是将客户端与服务端分离,另一个是提供日志代理。日志代理上面已经说了,现在说怎么实现客户端与服务端的分离。
在客户端调用服务端的服务时,我们一般会采用WCF,WebService之类的服务提供者,但是我们的项目比较特殊,他的客户可能会要求使用客户端与服务端分离,也有可能要求他们一起部署,及最简单的所有的东西都在一起,看上去是一个大个的客户端。
所以在开发的时候,要求客户端程序员,不能直接new出任何服务,所有的服务必须通过GetService获取,这样,根据客户的要求来实现分离或者整合,因为所有的操作都是在动态代理中执行的,所以只需要将动态代理的代理结果交给Communication组件既可以完成。
=========Communication===========
Communication组件是基本组件之一,负责执行动态代理传递过来的结果,其接口有两个方法:
- /// <summary>
- /// 执行操作
- /// </summary>
- /// <param name="method">函数信息</param>
- /// <param name="parameter">调用参数</param>
- object Execute(String method, Object parameter);
- /// <summary>
- /// 获取或设置异步接口调用的中转委托信息
- /// </summary>
- void AsycExecute(String method, Object parameter, Delegate Continue);
通过这两个方法的具体执行内容的变换,就可以替换为不同的服务端操作了。
==============DynamicProxy=======================
部分动态代理的代码:
拦截器(ServiceInterceptor):
- /// <summary>
- /// 服务拦截器
- /// </summary>
- public class ServiceInterceptor : IInterceptor
- {
- /// <summary>
- /// 获取或设置函数操作之前要执行的委托
- /// </summary>
- public Action<Object> BeforeMethod { get; set; }
- /// <summary>
- /// 函数操作之后要执行的委托
- /// </summary>
- public Action<Object> AfterMethod { get; set; }
- /// <summary>
- /// 函数操作之前要执行的委托的参数
- /// </summary>
- public Object BeforeMethodParameter { get; set; }
- /// <summary>
- /// 函数操作之后要执行的委托的参数
- /// </summary>
- public Object AfterMethodParameter { get; set; }
- /// <summary>
- /// 获取或设置接口调用的中转委托信息
- /// </summary>
- public Func<String, Object, Object> InterfaceInvoke { get; set; }
- /// <summary>
- /// 获取或设置异步接口调用的中转委托信息
- /// </summary>
- public Action<String, Object, Delegate> AsycInterfaceInvoke { get; set; }
- /// <summary>
- /// 异步后续处理函数
- /// </summary>
- public Delegate Continue { get; set; }
- /// <summary>
- /// 获取或设置是否为接口
- /// </summary>
- public bool IsInterface { get; set; }
- /// <summary>
- /// 拦截
- /// </summary>
- public void Intercept(IInvocation invocation)
- {
- // 前操作不为空,执行
- if (BeforeMethod != null)
- {
- BeforeMethod(BeforeMethodParameter);
- }
- if (IsInterface)
- {
- // 接口
- if ((InterfaceInvoke != null || AsycInterfaceInvoke != null)
- && invocation.Method.DeclaringType != null)
- {
- // 接口委托不为空,接口定义类型不为空
- if (Continue == null)
- {
- // 执行接口委托,并设置返回值
- invocation.ReturnValue = InterfaceInvoke(String.Format("{0}.{1}", invocation.Method.DeclaringType.FullName, invocation.Method.Name), invocation.Arguments);
- }
- else
- {
- // 执行异步操作
- AsycInterfaceInvoke(String.Format("{0}.{1}", invocation.Method.DeclaringType.FullName, invocation.Method.Name), invocation.Arguments, Continue);
- }
- }
- }
- else
- {
- invocation.Proceed();
- }
- // 后操作不为空,执行
- if (AfterMethod != null)
- {
- AfterMethod(AfterMethodParameter);
- }
- }
- }
- /// <summary>
- /// 动态代理
- /// </summary>
- public static class DynamicProxy
- {
- /// <summary>
- /// 获取或设置日志
- /// </summary>
- public static ILog Logger { get; set; }
- /// <summary>
- /// 获取或设置接口调用的中转委托信息
- /// </summary>
- public static Func<String, Object, Object> InterfaceInvoke { get; set; }
- /// <summary>
- /// 获取或设置异步接口调用的中转委托信息
- /// </summary>
- public static Action<String, Object, Delegate> AsycInterfaceInvoke { get; set; }
- /// <summary>
- /// 获取含有代理的实例
- /// </summary>
- /// <param name="typeName">实例类型</param>
- /// <param name="beforeMethod">函数操作之前要执行的委托</param>
- /// <param name="afterMethod">函数操作之后要执行的委托</param>
- /// <param name="beforeMethodParameter">函数操作之前要执行的委托的参数</param>
- /// <param name="afterMethodParameter">函数操作之后要执行的委托的参数</param>
- /// <returns>含有代理类的实例</returns>
- public static Object GetInstance(String typeName, Action<Object> beforeMethod, Action<Object> afterMethod,
- Object beforeMethodParameter = null, Object afterMethodParameter = null)
- {
- var assemblies = AppDomain.CurrentDomain.GetAssemblies();
- Type type = null;
- foreach (var assembly in assemblies)
- {
- type = assembly.GetType(typeName);
- if (type != null) break;
- }
- return CreateInstance(beforeMethod, afterMethod, beforeMethodParameter, afterMethodParameter, type);
- }
- /// <summary>
- /// 获取含有代理的实例
- /// </summary>
- /// <param name="beforeMethod">函数操作之前要执行的委托</param>
- /// <param name="afterMethod">函数操作之后要执行的委托</param>
- /// <param name="beforeMethodParameter">函数操作之前要执行的委托的参数</param>
- /// <param name="afterMethodParameter">函数操作之后要执行的委托的参数</param>
- /// <param name="type">实例类型</param>
- /// <returns>含有代理类的实例</returns>
- private static object CreateInstance(Action<object> beforeMethod, Action<object> afterMethod,
- object beforeMethodParameter, object afterMethodParameter, Type type)
- {
- if (type == null) return null;
- ProxyGenerator generator = new ProxyGenerator();
- var interceptor = new ServiceInterceptor
- {
- AfterMethod = afterMethod,
- AfterMethodParameter = afterMethodParameter,
- BeforeMethod = beforeMethod,
- BeforeMethodParameter = beforeMethodParameter,
- InterfaceInvoke = InterfaceInvoke,
- IsInterface = type.IsInterface,
- AsycInterfaceInvoke = AsycInterfaceInvoke
- };
- if (type.IsInterface)
- {
- return generator.CreateInterfaceProxyWithoutTarget(type, interceptor);
- }
- return generator.CreateClassProxy(type, interceptor);
- }
- /// <summary>
- /// 获取含有代理的实例
- /// </summary>
- /// <typeparam name="T">实例类型</typeparam>
- /// <param name="beforeMethod">函数操作之前要执行的委托</param>
- /// <param name="afterMethod">函数操作之后要执行的委托</param>
- /// <param name="beforeMethodParameter">函数操作之前要执行的委托的参数</param>
- /// <param name="afterMethodParameter">函数操作之后要执行的委托的参数</param>
- /// <returns>含有代理类的实例</returns>
- public static T GetInstance<T>(Action<Object> beforeMethod, Action<Object> afterMethod,
- Object beforeMethodParameter = null, Object afterMethodParameter = null)
- {
- Type type = typeof(T);
- return (T)CreateInstance(beforeMethod, afterMethod, beforeMethodParameter, afterMethodParameter, type);
- }
- /// <summary>
- /// 获取日志实例
- /// </summary>
- /// <typeparam name="T">实例类型</typeparam>
- /// <returns>包含有日志的代理实例</returns>
- public static T GetLogInstance<T>()
- {
- return GetInstance<T>(Logger.CallLog, Logger.CallLog);
- }
MethodCommunication类,该类中直接执行委托的方法,不区分客户端与服务端:
- /// <summary>
- /// 客户端服务通信方法类
- /// </summary>
- public class MethodCommunication : PluginBase, ICommunication
- {
- #region ICommunication Members
- /// <summary>
- /// 获取许可密钥
- /// </summary>
- /// <summary>
- /// 获取许可密钥
- /// </summary>
- public override string LicenseKey
- {
- get { return ""; }
- }
- /// <summary>
- /// 执行操作
- /// </summary>
- /// <param name="method">函数信息</param>
- /// <param name="parameter">调用参数</param>
- public object Execute(String method, Object parameter)
- {
- if (Executing != null) Executing(this, new EventArgs());
- OnExecuting();
- // 获取类型名称
- string[] classPart = method.Split('.');
- var classBuilder = new StringBuilder();
- for (int i = 0; i < classPart.Length - 1; i++)
- {
- classBuilder.Append(classPart[i]);
- classBuilder.Append('.');
- }
- classBuilder.Remove(classBuilder.Length - 1, 1);
- // 获取服务
- object service = GetInstance(classBuilder.ToString());
- if (service == null) throw new VerificationException("Didn't find the service at MethodCommunication.");
- // 获取函数信息
- Type serviceType = service.GetType();
- MethodInfo methodInfo = serviceType.GetMethod(classPart[classPart.Length - 1]);
- var temp = parameter as IEnumerable;
- IList<object> parameters = temp == null ? new List<object> { parameter } : temp.Cast<object>().ToList();
- // 执行
- object reslut = methodInfo.Invoke(service, parameters.ToArray());
- OnExcuted();
- if (Excuted != null) Excuted(this, new EventArgs());
- return reslut;
- }
- /// <summary>
- /// 获取或设置异步接口调用的中转委托信息
- /// </summary>
- public void AsycExecute(String method, Object parameter, Delegate Continue)
- {
- if (Continue.Method.GetParameters().Length == 0)
- {
- var task = new Task(() => Execute(method, parameter));
- task.ContinueWith(tr => Continue.DynamicInvoke());
- task.Start();
- }
- else
- {
- var task = new Task<Object>(() => Execute(method, parameter));
- task.ContinueWith(tr => Continue.DynamicInvoke(tr.Result));
- task.Start();
- }
- }
- /// <summary>
- /// 操作开始执行
- /// </summary>
- public virtual void OnExecuting()
- {
- }
- /// <summary>
- /// 操作执行结束
- /// </summary>
- public virtual void OnExcuted()
- {
- }
- /// <summary>
- /// 操作执行结束事件
- /// </summary>
- public event EventHandler Excuted;
- /// <summary>
- /// 操作执行开始事件
- /// </summary>
- public event EventHandler Executing;
- #endregion
- /// <summary>
- /// 获取实例
- /// </summary>
- /// <param name="typeFullName">类型名称</param>
- /// <returns>获取的实例</returns>
- protected virtual Object GetInstance(String typeFullName)
- {
- return App.GetService(typeFullName);
- }
WCF与其他的 ICommunication类这里就不给出了,基本上都是差不多的。
- .net的动态代理
- .Net动态代理Castle系列
- .Net动态代理Castle系列
- 关于.NET动态代理的介绍和应用简介
- 关于.NET动态代理的介绍和应用
- 关于.NET动态代理的介绍和应用简介
- 基于.net的可扩展框架设计 - 动态代理
- .Net动态代理Castle ( 了解创建动态代理 )
- 动态代理的意义
- Java的动态代理
- 动态代理的例子
- 动态代理的步骤
- 动态代理的实现
- JAVA的动态代理
- java的动态代理
- java的动态代理
- cglib的动态代理
- 动态代理的幕后
- Apache CXF实战之二 集成Sping与Web容器
- java生成唯一随即数
- UVa 131 The Psychic Poker Player
- 伪代码编码过程
- 删除文档空行
- .net的动态代理
- shell编程
- Apache CXF实战之三 传输Java对象
- Android Selector 与 Shape 基本用法
- 余弦相似度 —— Cosine Similarity
- vim大小写转换
- Hadoop 参数配置命令_简单范例
- Apache CXF实战之四 构建RESTful Web Service
- Sicily 1138. 寻宝之旅 树形DP