• C# 代理应用


    放心,这次不是说设计模式中的代理模式,说的是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;
                        else
                            returnValue = 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;
            }
        }

    还需要2个Attribute: 如上代码中用到的CachableAttribute和CachableEnabledAttribute

    CachableAttribute用来贴在各个函数签名上,可以指定cache的key等信息(继承自普通的Attribute)

    CachableEnabledAttribute用来关联 自定义proxy以及需要被代理的class的,用法是贴在被代理的class签名上(继承自ProxyAttribute)

    代码如下:

    public class CachableAttribute : Attribute
        {
            public string Location { get; set; }
            public string Key { get; set; }
            public CacheAction CacheAction { get; set; }
            public string KeyPath { get; set; }
            public object CacheObject { get; set; }
            public TimeSpan ExpireTimeSpan { get; set; }
            public DateTime AbsoluteExpireTime { get; set; }
    
            public string GenerateCacheKey()
            {
                //will be changed
                return string.Format("{0}", this.Key);
            }
        }
    public class CachableEnabledAttribute : ProxyAttribute
        {
            public override MarshalByRefObject CreateInstance(Type serverType)
            {
                MarshalByRefObject target = base.CreateInstance(serverType);
                CachableRealProxy rp = new CachableRealProxy(serverType, target);
                MarshalByRefObject obj = (MarshalByRefObject)rp.GetTransparentProxy();
                return obj;
            }
        }

    被代理的class需要继承自ContextBoundObject

    [CachableEnabled()]
        public class RealObject : ContextBoundObject
        {
            [Cachable(Location = "OrdersQuery", CacheAction = CacheAction.Read, Key = "OrderQueryService_QueryByFirstName_{0}")]
            public override QueryResult<QueryDto.OrderDto> QueryByFirstName(string firstName, PagingInfo pgInfo)
            {
                QueryResult<QueryDto.OrderDto> lst = new QueryResult<QueryDto.OrderDto>();
                lst.List = new List<QueryDto.OrderDto>();
                lst.TotalCount = 1000;
                for (int i = 0; i < 1;i++ )
                {
                    OrderDto o = new OrderDto();
                    o.BuyWhat = string.Format("Buywhat {0}", DateTime.Now.ToString());
                    o.FirstName = string.Format("FirstName {0}", DateTime.Now.ToString());
                    o.LastName = string.Format("LastName {0}", DateTime.Now.ToString());
                    o.Email = string.Format("Email {0}", DateTime.Now.ToString());
                    o.OrderID = Guid.NewGuid();
                    lst.List.Add(o);
                }
                return lst;
            }
        }

    看下控制台测试代码:

                RealObject srv1 = new RealObject();
                while (true)
                {
                    Thread.Sleep(1000);  //每隔1s执行调用,看看返回的时间是否相同,相同则代表已经是cachable的了
                    QueryResult<OrderDto> lst = srv1.QueryByFirstName("aaron", new CoreFramework.QueryService.PagingInfo() { PageIndex = 0, PageSize = 10, OrderByColumn = "FirstName", IsAscendingSort = true });
                    foreach (OrderDto order in lst.List)
                    {
                        string msg = string.Format("{0}-{1}-{2}-{3}", order.OrderID, order.FirstName, order.LastName, order.BuyWhat);
                        Console.WriteLine(msg);
                    }
                }

    运行效果图:

    搞定。
  • 相关阅读:
    Java 技术笔记
    idea启动TOMCAT html 乱码
    IntelliJ IDEA 导入新项目
    InterlliJ Debug方式启动:method breakpoints may dramatically show down debugging
    intelliJ idea #region 代码折叠
    Console 程序在任务计划程序无法读写文件
    Java 发送邮件
    MySQL 索引
    MySQL 临时表
    11 帧差法获取运动
  • 原文地址:https://www.cnblogs.com/aarond/p/RealProxy.html
Copyright © 2020-2023  润新知