輸入參數索引做爲緩存鍵的實現緩存
using MJD.Framework.CrossCutting; using MJD.Framework.ICache; using System; using System.Collections.Generic; using System.Linq; namespace MJD.Framework.Aop.Cache { /// <summary> /// 方法的緩存屬性(線性不安全) /// </summary> [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public class CacheAttribute : AopAttribute { #region fields private short _index1 = -1; private short _index2 = -1; private short _index3 = -1; #endregion #region protected fields protected string Prefix = string.Empty;//緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴 protected string Key = string.Empty; protected string BucketName = string.Empty; #endregion #region Otors /// <summary> /// 定義緩存關鍵字來緩存 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> protected CacheAttribute(string bucketName, string prefix) { BucketName = bucketName; Prefix = prefix; } /// <summary> /// 定義緩存關鍵字來緩存 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="key">緩存鍵</param> public CacheAttribute(string bucketName, string prefix, string key) : this(bucketName, prefix) { if (string.IsNullOrEmpty(key)) throw new ArgumentException("緩存鍵不能爲空"); Key = string.Format("{0}:{1}", Prefix, key); } /// <summary> /// 使用當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex">對應的當前參數的緩存鍵所在的參數索引位置</param> public CacheAttribute(string bucketName, string prefix, short keyIndex) : this(bucketName, prefix) { if (keyIndex < 0) throw new ArgumentException("關鍵值的參數索引需大於0"); _index1 = keyIndex; } /// <summary> /// 使用多個當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex1">對應的當前參數的緩存鍵所在的參數索引位置1</param> /// <param name="keyIndex2">對應的當前參數的緩存鍵所在的參數索引位置2</param> public CacheAttribute(string bucketName, string prefix, short keyIndex1, short keyIndex2) : this(bucketName, prefix) { if (keyIndex1 < 0 || keyIndex2 < 0) throw new ArgumentException("關鍵值的參數索引需大於0"); _index1 = keyIndex1; _index2 = keyIndex2; } /// <summary> /// 使用多個當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex1">對應的當前參數的緩存鍵所在的參數索引位置1</param> /// <param name="keyIndex2">對應的當前參數的緩存鍵所在的參數索引位置2</param> /// <param name="keyIndex3">對應的當前參數的緩存鍵所在的參數索引位置3</param> public CacheAttribute(string bucketName, string prefix, short keyIndex1, short keyIndex2, short keyIndex3) : this(bucketName, prefix) { if (keyIndex1 < 0 || keyIndex2 < 0 || keyIndex3 < 0) throw new ArgumentException("關鍵值的參數索引不能小於零"); _index1 = keyIndex1; _index2 = keyIndex2; _index3 = keyIndex3; } #endregion #region override public override object PreCall(object[] inputArgs, out object[] outputs) { outputs = new object[0]; var result = IocContainer.Resolve<ICacheService>(BucketName).Get<object>(GetKey(inputArgs)); return result.Success ? result.Value : null; } public override void Called(object resultValue, object[] inputArgs, object[] outputs) { IocContainer.Resolve<ICacheService>(BucketName).Upsert<object>(GetKey(inputArgs), resultValue); } public override void OnException(Exception e, Dictionary<string, object> inputArgs) { } protected virtual string GetKey(object[] inputArgs) { if (string.IsNullOrEmpty(Key)) { if (Math.Max(Math.Max(_index1, _index2), _index3) >= inputArgs.Count()) throw new ArgumentException("關鍵值的參數索引不能大於參數總個數"); string prefix1 = _index1 >= 0 ? inputArgs[_index1].ToJson() : ""; string prefix2 = _index2 >= 0 ? "-" + inputArgs[_index2].ToJson() : ""; string prefix3 = _index3 >= 0 ? "-" + inputArgs[_index3].ToJson() : ""; Key = string.Format("{0}:{1}{2}{3}",Prefix, prefix1, prefix2, prefix3); } return Key; } #endregion } }
輸入參數是對象,經過輸入參數對象的屬性的值來做爲緩存鍵安全
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace MJD.Framework.Aop.Cache { /// <summary> /// 根據屬性來設置緩存的關鍵字 /// </summary> public class CacheWithPropertyAttribute : CacheAttribute { #region fields private List<string> _properties = null; private byte _index = 0; #endregion #region Octors /// <summary> /// 根據方法的第一個參數的屬性設置 /// </summary> /// <param name="bucketName">緩存Bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="properties">屬性名</param> public CacheWithPropertyAttribute(string bucketName, string prefix, params string[] properties) : base(bucketName, prefix) { if (properties == null || properties.Length == 0) throw new ArgumentException("設置的properties個數必須大於1"); _properties = properties.ToList(); } /// <summary> /// 根據方法的第一個參數的屬性設置 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="index">要設置爲緩存的方法參數的索引,索引下標從0開始</param> /// <param name="properties">屬性名</param> public CacheWithPropertyAttribute(string bucketName, string prefix, byte index, params string[] properties) : base(bucketName, prefix) { if (index < 0) throw new ArgumentException("關鍵值的參數索引不能小於零"); if (properties == null || properties.Length == 0) throw new ArgumentException("設置的properties個數必須大於1"); _properties = properties.ToList(); _index = index; } #endregion #region override public override object PreCall(object[] inputArgs, out object[] outputs) { return base.PreCall(inputArgs, out outputs); } #endregion protected override string GetKey(object[] inputArgs) { if (string.IsNullOrEmpty(Key)) { Key += base.Prefix + ":"; object instance = inputArgs[_index]; foreach (var property in _properties) { Key += GetPropertyValue(instance, property) + "-"; } } return Key.TrimEnd('-'); } private object GetPropertyValue(object instance, string propertyName) { BindingFlags flag = BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.IgnoreCase | BindingFlags.Public; Type type = instance.GetType(); var property = type.GetProperty(propertyName, flag); if (property == null) throw new ArgumentException(string.Format("獲取緩存出錯,類型{0}中沒有找到屬性{1}", type, propertyName)); return property.GetValue(instance, null); } } }
經過輸入參數索引位置移除緩存的aop屬性ide
using MJD.Framework.CrossCutting; using MJD.Framework.ICache; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MJD.Framework.Aop.Cache { /// <summary> /// 移除緩存特性 /// </summary> public class RemoveCacheAttribute : CacheAttribute { #region Otors /// <summary> /// 定義緩存關鍵字來緩存 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> protected RemoveCacheAttribute(string bucketName, string prefix) : base(bucketName, prefix) { } /// <summary> /// 定義緩存關鍵字來緩存 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="key">緩存鍵</param> public RemoveCacheAttribute(string bucketName, string prefix, string key) : base(bucketName, prefix, key) { } /// <summary> /// 使用當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex">對應的當前參數的緩存鍵所在的參數索引位置</param> public RemoveCacheAttribute(string bucketName, string prefix, short keyIndex) : base(bucketName, prefix, keyIndex) { } /// <summary> /// 使用多個當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex1">對應的當前參數的緩存鍵所在的參數索引位置1</param> /// <param name="keyIndex2">對應的當前參數的緩存鍵所在的參數索引位置2</param> public RemoveCacheAttribute(string bucketName, string prefix, short keyIndex1, short keyIndex2) : base(bucketName, prefix, keyIndex1, keyIndex2) { } /// <summary> /// 使用多個當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex1">對應的當前參數的緩存鍵所在的參數索引位置1</param> /// <param name="keyIndex2">對應的當前參數的緩存鍵所在的參數索引位置2</param> /// <param name="keyIndex3">對應的當前參數的緩存鍵所在的參數索引位置3</param> public RemoveCacheAttribute(string bucketName, string prefix, short keyIndex1, short keyIndex2, short keyIndex3) : base(bucketName, prefix, keyIndex1, keyIndex2, keyIndex3) { } #endregion #region override public override void Called(object resultValue, object[] inputArgs, object[] outputs) { } public override object PreCall(object[] inputArgs, out object[] outputs) { IocContainer.Resolve<ICacheService>(BucketName).Remove(GetKey(inputArgs)); outputs = new object[0]; return null; } #endregion } }
經過輸入參數屬性的值做爲緩存鍵來移除緩存this
using MJD.Framework.CrossCutting; using MJD.Framework.ICache; namespace MJD.Framework.Aop.Cache { /// <summary> /// 移除緩存特性(調用成功後移除) /// </summary> public class RemoveCacheWithPropertyAttribute : CacheWithPropertyAttribute { #region Octors /// <summary> /// 根據方法的第一個參數的屬性設置 /// </summary> /// <param name="bucketName">緩存Bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="properties">屬性名</param> public RemoveCacheWithPropertyAttribute(string bucketName, string prefix, params string[] properties) : base(bucketName, prefix, properties) { } /// <summary> /// 根據方法的第一個參數的屬性設置 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="index">要設置爲緩存的方法參數的索引,索引下標從0開始</param> /// <param name="properties">屬性名</param> public RemoveCacheWithPropertyAttribute(string bucketName, string prefix, byte index, params string[] properties) : base(bucketName, prefix, index, properties) { } #endregion #region override public override void Called(object resultValue, object[] inputArgs, object[] outputs) { IocContainer.Resolve<ICacheService>(BucketName).Remove(GetKey(inputArgs)); } public override object PreCall(object[] inputArgs, out object[] outputs) { //IocContainer.Resolve<ICacheService>(BucketName).Remove(GetKey(inputArgs)); outputs = new object[0]; return null; } #endregion } }
更新1spa
using MJD.Framework.CrossCutting; using MJD.Framework.ICache; namespace MJD.Framework.Aop.Cache { /// <summary> /// 更新緩存特性 /// </summary> public class UpdateCacheAttribute : CacheAttribute { #region Otors /// <summary> /// 定義緩存關鍵字來緩存 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> protected UpdateCacheAttribute(string bucketName, string prefix) : base(bucketName, prefix) { } /// <summary> /// 定義緩存關鍵字來緩存 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="key">緩存鍵</param> public UpdateCacheAttribute(string bucketName, string prefix, string key) : base(bucketName, prefix, key) { } /// <summary> /// 使用當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex">對應的當前參數的緩存鍵所在的參數索引位置</param> public UpdateCacheAttribute(string bucketName, string prefix, short keyIndex) : base(bucketName, prefix, keyIndex) { } /// <summary> /// 使用多個當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex1">對應的當前參數的緩存鍵所在的參數索引位置1</param> /// <param name="keyIndex2">對應的當前參數的緩存鍵所在的參數索引位置2</param> public UpdateCacheAttribute(string bucketName, string prefix, short keyIndex1, short keyIndex2) : base(bucketName, prefix, keyIndex1, keyIndex2) { } /// <summary> /// 使用多個當前參數來緩存,索引位置從0開始 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="keyIndex1">對應的當前參數的緩存鍵所在的參數索引位置1</param> /// <param name="keyIndex2">對應的當前參數的緩存鍵所在的參數索引位置2</param> /// <param name="keyIndex3">對應的當前參數的緩存鍵所在的參數索引位置3</param> public UpdateCacheAttribute(string bucketName, string prefix, short keyIndex1, short keyIndex2, short keyIndex3) : base(bucketName, prefix, keyIndex1, keyIndex2, keyIndex3) { } #endregion #region override public override void Called(object resultValue, object[] inputArgs, object[] outputs) { IocContainer.Resolve<ICacheService>(BucketName).Upsert<object>(GetKey(inputArgs), resultValue); } public override object PreCall(object[] inputArgs, out object[] outputs) { outputs = new object[0]; return null; } #endregion } }
更新2code
using MJD.Framework.CrossCutting; using MJD.Framework.ICache; namespace MJD.Framework.Aop.Cache { /// <summary> /// 更新緩存特性 /// </summary> public class UpdateCacheWithPropertyAttribute : CacheWithPropertyAttribute { #region Octors /// <summary> /// 根據方法的第一個參數的屬性設置 /// </summary> /// <param name="bucketName">緩存Bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="properties">屬性名</param> public UpdateCacheWithPropertyAttribute(string bucketName, string prefix, params string[] properties) : base(bucketName, prefix, properties) { } /// <summary> /// 根據方法的第一個參數的屬性設置 /// </summary> /// <param name="bucketName">緩存bucket</param> /// <param name="prefix">緩存的前綴,避免使用ID做爲緩存鍵時與其餘緩存衝突,必須是獨一無二的前綴</param> /// <param name="index">要設置爲緩存的方法參數的索引,索引下標從0開始</param> /// <param name="properties">屬性名</param> public UpdateCacheWithPropertyAttribute(string bucketName, string prefix, byte index, params string[] properties) : base(bucketName, prefix, index, properties) { } #endregion #region override public override void Called(object resultValue, object[] inputArgs, object[] outputs) { IocContainer.Resolve<ICacheService>(BucketName).Upsert<object>(GetKey(inputArgs), resultValue); } public override object PreCall(object[] inputArgs, out object[] outputs) { outputs = new object[0]; return null; } #endregion } }