Welcome

首页 / 软件开发 / C# / C# 代理应用:Cachable

C# 代理应用:Cachable2014-04-08 cnblogs Aaron放心,这次不是说设计模式中的代理模式,说的是C#的RealProxy的用法,主要用于:通过给class 贴标签,让class做更多的工作,比如判断是否存在缓存,有则直接返回缓存object,没有则保存为缓 存,等待下次请求是可以更快的获取数据(当然这只是其中一种常用用途,MVC的Action就是采用这种 方式)

下面是序列图:

.Net Object Generation interceptor属于.NET自身行为,不需要额外写代码。

Code Consumer指想调用RealObject来进行调用的对象,比如控制台程序,或者WEB程序。

ProxyAttribute里定义了具体代理类是哪个,这个代理类是自己 继承RealProxy写的一个代理类, 这个类中需要加入前置、后置、环绕等方法(具体根据需求)

下面我们来看具体如何在.Net中实现:

public class FollowAction{public bool StopExecute { get; set; } //用于在前置方法中,指示是否停止执行真正的方法体,比如已经找到了cache value,因此不需要继续运行方法体的情况public object Result { get; set; }//保存cache value的变量}public abstract class CachableRealProxy : RealProxy{private MarshalByRefObject target;public MyAOPRealProxy(Type objType, MarshalByRefObject obj): base(objType){target = obj;}public override IMessage Invoke(IMessage msg){IMessage retMsg = null;IMethodCallMessage methodCall = (IMethodCallMessage)msg;IMethodReturnMessage methodReturn = null;object[] copiedArgs = Array.CreateInstance(typeof(object), methodCall.Args.Length) as object[];methodCall.Args.CopyTo(copiedArgs, 0);if (msg is IConstructionCallMessage){IConstructionCallMessage ccm = (IConstructionCallMessage)msg;RemotingServices.GetRealProxy(target).InitializeServerObject(ccm);ObjRef oRef = RemotingServices.Marshal(target);RemotingServices.Unmarshal(oRef);retMsg = EnterpriseServicesHelper.CreateConstructionReturnMessage(ccm, (MarshalByRefObject)this.GetTransparentProxy());}else{bool aopAttributeExists = false;object[] attrs = methodCall.MethodBase.GetCustomAttributes(false);if (attrs != null && attrs.Count() > 0){foreach(object o in attrs){CachableAttribute attr = o as CachableAttribute;if (attr != null){aopAttributeExists = true;break;}}}FollowAction follow=null;if (aopAttributeExists)follow = this.PreProcess(msg);try{object returnValue = null;if (follow != null && follow.StopExecute)returnValue = follow.Result;elsereturnValue = methodCall.MethodBase.Invoke(this.target, copiedArgs);methodReturn = new ReturnMessage(returnValue, copiedArgs, copiedArgs.Length, methodCall.LogicalCallContext, methodCall);if (follow == null || !follow.StopExecute)if (aopAttributeExists)this.PostProcess(msg, methodReturn);}catch (Exception ex){if (null != ex.InnerException){methodReturn = new ReturnMessage(ex.InnerException, methodCall);}else{methodReturn = new ReturnMessage(ex, methodCall);}}retMsg = methodReturn;}return retMsg;} public override FollowAction PreProcess(System.Runtime.Remoting.Messaging.IMessage requestMsg)//处理前置方法{bool cacheDefinationTagExists = true;CachableAttribute cacheDefine = CheckCacheDefinationTag(requestMsg, ref cacheDefinationTagExists);if (!cacheDefinationTagExists)return null;string cacheKey = cacheDefine.GenerateCacheKey();object o=CacheManager.Instance().GetCacheCore().Get(cacheDefine.Location, cacheKey);if (o != null){FollowAction follow = new FollowAction();follow.Result = o;follow.StopExecute = true;return follow;}return null;}public override void PostProcess(System.Runtime.Remoting.Messaging.IMessage requestMsg, System.Runtime.Remoting.Messaging.IMessage responseMsg)//处理后置方法{bool cacheDefinationTagExists = true;CachableAttribute cacheDefine = CheckCacheDefinationTag(requestMsg, ref cacheDefinationTagExists);if (!cacheDefinationTagExists)return;ReturnMessage returnMsg = (ReturnMessage)responseMsg;string cacheKey = cacheDefine.GenerateCacheKey();CacheManager.Instance().GetCacheCore().Set(cacheDefine.Location, cacheKey, returnMsg.ReturnValue);}private static CachableAttribute CheckCacheDefinationTag(System.Runtime.Remoting.Messaging.IMessage requestMsg, ref bool cacheDefinationTagExists)//Help函数{IMethodCallMessage methodCall = (IMethodCallMessage)requestMsg;object[] attrs = methodCall.MethodBase.GetCustomAttributes(typeof(CachableAttribute), false);if (attrs == null || attrs.Count() <= 0)cacheDefinationTagExists = false;CachableAttribute cacheDefine = attrs[0] as CachableAttribute;if (cacheDefine == null)cacheDefinationTagExists = false;return cacheDefine;}}