中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

緩(huan)存(cun)篇~第八(ba)回(hui) Redis實現基于方法簽名的數據集緩(huan)存(cun)~續(優化緩(huan)存(cun)中的key)

返回目錄

上一講主要是說如何將數據集存儲到redis服務器里,而今(jin)天主要說(shuo)的是緩存(cun)里的鍵名,我們(men)習慣叫它key.

redis或者其(qi)它緩存組(zu)件(jian)實現的(de)存儲機(ji)制(zhi)里(li),它將很多方(fang)(fang)法對應的(de)數據(ju)集存儲在(zai)一個(ge)公共的(de)空(kong)(kong)間(jian)里(li),這個(ge)空(kong)(kong)間(jian)足夠(gou)大,當然它也是共享(xiang)(xiang)的(de),沒有(you)具(ju)體的(de)分區,也就是說(shuo),如果你的(de)key重復了(le),那這事就有(you)點(dian)壞味道了(le),對于一個(ge)項目(mu)肯定(ding)沒什么問題,只(zhi)要做到方(fang)(fang)法名(ming)不相同(tong)就可以(yi),但是,如果是多個(ge)項目(mu)共享(xiang)(xiang)一個(ge)緩存服務器(緩存中間(jian)件(jian),這是很正常的(de),沒有(you)什么公司一個(ge)項目(mu)對應一個(ge)緩存服務器,沒必(bi)要,當你的(de)項目(mu)足夠(gou)大時,可以(yi)會有(you)分模塊(kuai)去(qu)做緩存服務器的(de)概念(nian)),今天的(de)重點(dian)就是在(zai)攔(lan)截(jie)組(zu)件(jian)中優(you)化我們的(de)key,對于get和put,remove方(fang)(fang)法都要進行優(you)化.

 /// <summary>
    /// 表(biao)示(shi)用(yong)于方法緩存功(gong)能的攔(lan)截行為。
    /// </summary>
    public class CachingBehavior : IInterceptionBehavior
    {
        /// <summary>
        /// 緩(huan)存(cun)項(xiang)目名稱(cheng),每個項(xiang)目有自己(ji)的名稱(cheng)
        /// 避免緩(huan)存鍵名(ming)重復
        /// </summary>
        static readonly string cacheProjectName = System.Configuration.ConfigurationManager.AppSettings["CacheProjectName"] ?? "DataSetCache";


        #region Private Methods
        /// <summary>
        /// 根據指定的<see cref="CachingAttribute"/>以及<see cref="IMethodInvocation"/>實例(li),
        /// 獲取與某一特(te)定參數值相關的鍵名。
        /// </summary>
        /// <param name="cachingAttribute"><see cref="CachingAttribute"/>實例。</param>
        /// <param name="input"><see cref="IMethodInvocation"/>實例。</param>
        /// <returns>與某一特定參數值相關的鍵名。</returns>
        private string GetValueKey(CachingAttribute cachingAttribute, IMethodInvocation input)
        {
            switch (cachingAttribute.Method)
            {
                // 如果(guo)是Remove,則(ze)不存在(zai)特定(ding)值鍵名,所有的(de)以(yi)該方法名稱(cheng)相(xiang)關的(de)緩存都需要(yao)清(qing)除
                case CachingMethod.Remove:
                    return null;
                // 如果是Get或者Put,則需要產生一(yi)個針對(dui)特定(ding)參數值(zhi)的鍵名
                case CachingMethod.Get:
                case CachingMethod.Put:
                    if (input.Arguments != null &&
                        input.Arguments.Count > 0)
                    {
                        var sb = new StringBuilder();
                        for (int i = 0; i < input.Arguments.Count; i++)
                        {
                            if (input.Arguments[i].GetType().BaseType == typeof(LambdaExpression))//lambda處理
                            {
                                var exp = input.Arguments[i] as LambdaExpression;
                                var arr = ((System.Runtime.CompilerServices.Closure)(((System.Delegate)(Expression.Lambda(exp).Compile().DynamicInvoke())).Target)).Constants;

                                Type t = arr[0].GetType();
                                string result = "";

                                foreach (var member in t.GetFields())
                                {
                                    result += member.Name + "_" + t.GetField(member.Name).GetValue(arr[0]) + "_";
                                }
                                result = result.Remove(result.Length - 1);
                                sb.Append(result.ToString());
                            }
                            else if (input.Arguments[i].GetType() != typeof(string)//類和結構體(ti)處理
                                && input.Arguments[i].GetType().BaseType.IsClass)
                            {
                                var obj = input.Arguments[i];
                                Type t = obj.GetType();
                                string result = "";

                                foreach (var member in t.GetProperties())//公開屬性
                                {
                                    result += member.Name + "_" + t.GetProperty(member.Name).GetValue(obj) + "_";
                                }
                                foreach (var member in t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))//私有和公用字段
                                {
                                    result += member.Name + "_" + t.GetField(member.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj) + "_";
                                }   result
= result.Remove(result.Length - 1); sb.Append(result.ToString());  } else//簡(jian)單值類型處理  {  sb.Append(input.Arguments[i].ToString()); } if (i != input.Arguments.Count - 1) sb.Append("_");   } return sb.ToString(); }  else return "NULL"; default: throw new InvalidOperationException("無效的緩存方式。"); } } #endregion #region IInterceptionBehavior Members /// <summary> /// 獲取當(dang)前行為需要攔截的對象類(lei)型接(jie)口(kou)。 /// </summary> /// <returns>所有需(xu)要攔截的對象類型接口。</returns> public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } /// <summary> /// 通過實現此方法來攔截(jie)調用并執行(xing)所需的(de)攔截(jie)行(xing)為。 /// </summary> /// <param name="input">調用攔截目(mu)標時的輸入信息。</param> /// <param name="getNext">通過行(xing)為鏈來獲(huo)取下一(yi)個攔截行(xing)為的(de)委(wei)托。</param> /// <returns>從(cong)攔截(jie)目標獲得的返回信息。</returns> public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)  { var method = input.MethodBase; //鍵值前綴 string prefix = cacheProjectName + "_" + input.Target.ToString() + "_"; //鍵名(ming),在put和get時(shi)使用 var key = prefix + method.Name; if (method.IsDefined(typeof(CachingAttribute), false)) { var cachingAttribute = (CachingAttribute)method.GetCustomAttributes(typeof(CachingAttribute), false)[0]; var valKey = GetValueKey(cachingAttribute, input); switch (cachingAttribute.Method) { case CachingMethod.Get: try { if (CacheManager.Instance.Exists(key, valKey)) { var obj = CacheManager.Instance.Get(key, valKey); var arguments = new object[input.Arguments.Count];  input.Arguments.CopyTo(arguments, 0); return new VirtualMethodReturn(input, obj, arguments); } else { var methodReturn = getNext().Invoke(input, getNext);  CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue); return methodReturn; } }  catch (Exception ex)  { return new VirtualMethodReturn(input, ex);  }  case CachingMethod.Put: try { var methodReturn = getNext().Invoke(input, getNext); if (CacheManager.Instance.Exists(key)) { if (cachingAttribute.Force) { CacheManager.Instance.Remove(key); CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue); } else  CacheManager.Instance.Put(key, valKey, methodReturn.ReturnValue);  } else CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue); return methodReturn; } catch (Exception ex) {  return new VirtualMethodReturn(input, ex); } case CachingMethod.Remove: try { var removeKeys = cachingAttribute.CorrespondingMethodNames;  foreach (var removeKey in removeKeys) {  string delKey = prefix + removeKey; if (CacheManager.Instance.Exists(delKey))  CacheManager.Instance.Remove(delKey); } var methodReturn = getNext().Invoke(input, getNext); return methodReturn;  } catch (Exception ex) { return new VirtualMethodReturn(input, ex); }   default: break; } } return getNext().Invoke(input, getNext); } /// <summary> /// 獲(huo)取一個<see cref="Boolean"/>值,該值表示當前攔截行為被調用時,是否真的需要執行 /// 某些操作。 /// </summary> public bool WillExecute { get { return true; } } #endregion }

優化后的(de)key的(de)結構(gou)為(wei)項(xiang)目前(qian)綴_項(xiang)目命(ming)名(ming)空(kong)間_方法(fa)名(ming),這樣的(de)設計(ji)我(wo)想它不會再有重復了,事實上,如果你(ni)的(de)項(xiang)目正規的(de)話,只(zhi)要有(項(xiang)目命(ming)名(ming)空(kong)間_方法(fa)名(ming))這一(yi)層控(kong)制就(jiu)可以做到key值唯一(yi)了,而為(wei)了避免意外,我(wo)們還是加了一(yi)個項(xiang)目前(qian)綴CacheProjectName!

我們可以看一(yi)下緩存存儲時的鍵名(ming)截圖

返回目錄

 

posted @ 2014-11-06 11:00  張占嶺  閱讀(1854)  評論(0)    收藏  舉報