博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AOP 横向切面-热插拔缓存
阅读量:5057 次
发布时间:2019-06-12

本文共 22676 字,大约阅读时间需要 75 分钟。

PetShop 部分代码,可以看到每个函数都需要追加HttpRuntime.Cache.Add,都需要在函数体内进行操作。这样子也搞不清楚哪些函数追加了缓存。项目一大就不好控制

public static IList
GetCategories() { Category cat = new Category(); if (!enableCaching) return cat.GetCategories(); string key = "category_all"; IList
data = (IList
)HttpRuntime.Cache[key]; // Check if the data exists in the data cache if (data == null) { // If the data is not in the cache then fetch the data from the business logic tier data = cat.GetCategories(); // Create a AggregateCacheDependency object from the factory AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency(); // Store the output in the data cache, and Add the necessary AggregateCacheDependency object HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(categoryTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null); } return data;}

vs2012 mvc4
解决方法 AOP
需要引用微软企业库.
Microsoft.Practices.EnterpriseLibrary.Caching.dll
Microsoft.Practices.ServiceLocation.dll
Microsoft.Practices.Unity.dll
Microsoft.Practices.Unity.Configuration.dll
Microsoft.Practices.Unity.Interception.dll
Microsoft.Practices.Unity.Interception.Configuration.dll
配置文件

CachingAttribute 特性设置

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MvcApplication1{    ///     /// 表示由此特性所描述的方法,能够获得来自基础结构层所提供的缓存功能。    ///     [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]    public class CachingAttribute : Attribute    {        #region Ctor        ///         /// 初始化一个新的
CachingAttribute
类型。 ///
/// 缓存方式。 public CachingAttribute(CachingMethod method) { this.Method = method; } /// /// 初始化一个新的
CachingAttribute
类型。 ///
/// 缓存方式 /// 设置超时时间(秒) public CachingAttribute(CachingMethod method, int TimeOutSeconds) : this(method) { this.TimeOutSeconds = TimeOutSeconds; } /// /// 初始化一个新的
CachingAttribute
类型。 ///
/// 缓存方式。 /// /// 与当前缓存方式相关的方法名称。注:此参数仅在缓存方式为Remove时起作用。 /// public CachingAttribute(CachingMethod method, params string[] correspondingMethodNames) : this(method) { this.CorrespondingMethodNames = correspondingMethodNames; } #endregion #region Public Properties /// /// 设置缓存的超时时间 /// public int TimeOutSeconds { get; set; } /// /// 获取或设置缓存方式。 /// public CachingMethod Method { get; set; } /// /// 获取或设置一个
值,该值表示当缓存方式为Put时,是否强制将值写入缓存中。 ///
public bool Force { get; set; } /// /// 获取或设置与当前缓存方式相关的方法名称。注:此参数仅在缓存方式为Remove时起作用。 /// public string[] CorrespondingMethodNames { get; set; } #endregion }
 
public enum CachingMethod    {        Remove=0,        Get=1,        Put = 2    }
}
ICacheProvider 接口设置

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MvcApplication1{    public interface ICacheProvider    {        #region Methods        ///         /// 向缓存中添加一个对象。        ///         /// 缓存的键值,该值通常是使用缓存机制的方法的名称。        /// 缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。        /// 需要缓存的对象。        void Add(string key, string valKey, object value, int TimeoutSeconds);        ///         /// 向缓存中更新一个对象。        ///         /// 缓存的键值,该值通常是使用缓存机制的方法的名称。        /// 缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。        /// 需要缓存的对象。        void Put(string key, string valKey, object value);        ///         /// 从缓存中读取对象。        ///         /// 缓存的键值,该值通常是使用缓存机制的方法的名称。        /// 缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。        /// 
被缓存的对象。
object Get(string key, string valKey); /// /// 从缓存中移除对象。 /// /// 缓存的键值,该值通常是使用缓存机制的方法的名称。 void Remove(string key); /// /// 获取一个
值,该值表示拥有指定键值的缓存是否存在。 ///
/// 指定的键值。 ///
如果缓存存在,则返回true,否则返回false。
bool Exists(string key); /// /// 获取一个
值,该值表示拥有指定键值和缓存值键的缓存是否存在。 ///
/// 指定的键值。 /// 缓存值键。 ///
如果缓存存在,则返回true,否则返回false。
bool Exists(string key, string valKey); #endregion }}

CachingBehavior

using Microsoft.Practices.EnterpriseLibrary.Caching;using Microsoft.Practices.Unity.InterceptionExtension;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MvcApplication1{    public class CachingBehavior : IInterceptionBehavior    {        public IEnumerable
GetRequiredInterfaces() { return Type.EmptyTypes; } #region Private Methods ///
/// 根据指定的
以及
实例, /// 获取与某一特定参数值相关的键名。 ///
///
实例。 ///
实例。 ///
与某一特定参数值相关的键名。 ///
/// 例如:
///
///
private string GetValueKey(CachingAttribute cachingAttribute, IMethodInvocation input) { switch (cachingAttribute.Method) { // 如果是Remove,则不存在特定值键名,所有的以该方法名称相关的缓存都需要清除 case CachingMethod.Remove: return null; // 如果是Get或者Put,则需要产生一个针对特定参数值的键名 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++) { 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 public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { var method = input.MethodBase; var key = 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); obj += "缓存"; 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); if (cachingAttribute.TimeOutSeconds > 0) { CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue, cachingAttribute.TimeOutSeconds); } else { 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); if (cachingAttribute.TimeOutSeconds > 0) { CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue, cachingAttribute.TimeOutSeconds); } else { CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue); } } else { if (cachingAttribute.TimeOutSeconds > 0) { CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue, cachingAttribute.TimeOutSeconds); } else { CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue); } } } else { if (cachingAttribute.TimeOutSeconds > 0) { CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue, cachingAttribute.TimeOutSeconds); } 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) { if (CacheManager.Instance.Exists(removeKey)) CacheManager.Instance.Remove(removeKey); } var methodReturn = getNext().Invoke(input, getNext); return methodReturn; } catch (Exception ex) { return new VirtualMethodReturn(input, ex); } default: break; } } Console.WriteLine("CachingBehavior"); return getNext().Invoke(input, getNext); } public bool WillExecute { get { return true; } } }}
 

ExceptionLoggingBehavior

using Microsoft.Practices.Unity.InterceptionExtension;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MvcApplication1{    public class ExceptionLoggingBehavior : IInterceptionBehavior    {        public IEnumerable
GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("ExceptionLoggingBehavior"); return getNext().Invoke(input, getNext); } public bool WillExecute { get { return true; } } }}

CacheManager

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MvcApplication1{    public sealed class CacheManager : ICacheProvider    {        #region Private Fields        private readonly ICacheProvider _cacheProvider;        private static readonly CacheManager _instance = new CacheManager();        #endregion        #region Ctor        static CacheManager() { }        private CacheManager()        {            _cacheProvider = new EntLibCacheProvider();        }        #endregion        #region Public Properties        ///         /// 获取
CacheManager
类型的单件(Singleton)实例。 ///
public static CacheManager Instance { get { return _instance; } } #endregion #region ICacheProvider Members /// /// 向缓存中添加一个对象。 /// /// 缓存的键值,该值通常是使用缓存机制的方法的名称。 /// 缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。 /// 需要缓存的对象。 public void Add(string key, string valKey, object value, int Timeoutseconds=60) { _cacheProvider.Add(key, valKey, value,Timeoutseconds); } /// /// 向缓存中更新一个对象。 /// /// 缓存的键值,该值通常是使用缓存机制的方法的名称。 /// 缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。 /// 需要缓存的对象。 public void Put(string key, string valKey, object value) { _cacheProvider.Put(key, valKey, value); } /// /// 从缓存中读取对象。 /// /// 缓存的键值,该值通常是使用缓存机制的方法的名称。 /// 缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。 ///
被缓存的对象。
public object Get(string key, string valKey) { return _cacheProvider.Get(key, valKey); } /// /// 从缓存中移除对象。 /// /// 缓存的键值,该值通常是使用缓存机制的方法的名称。 public void Remove(string key) { _cacheProvider.Remove(key); } /// /// 获取一个
值,该值表示拥有指定键值的缓存是否存在。 ///
/// 指定的键值。 ///
如果缓存存在,则返回true,否则返回false。
public bool Exists(string key) { return _cacheProvider.Exists(key); } /// /// 获取一个
值,该值表示拥有指定键值和缓存值键的缓存是否存在。 ///
/// 指定的键值。 /// 缓存值键。 ///
如果缓存存在,则返回true,否则返回false。
public bool Exists(string key, string valKey) { return _cacheProvider.Exists(key, valKey); } #endregion }}
EntLibCacheProvider

 

using Microsoft.Practices.EnterpriseLibrary.Caching;using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MvcApplication1{    public class EntLibCacheProvider : ICacheProvider    {        #region Private Fields        private readonly ICacheManager _cacheManager = CacheFactory.GetCacheManager();                #endregion        #region ICacheProvider Members        ///         /// 向缓存中添加一个对象。        ///         /// 缓存的键值,该值通常是使用缓存机制的方法的名称。        /// 缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。        /// 需要缓存的对象。        public void Add(string key, string valKey, object value,int Timeoutseconds)        {            Dictionary
dict = null; if (_cacheManager.Contains(key)) { dict = (Dictionary
)_cacheManager[key]; dict[valKey] = value; } else { dict = new Dictionary
(); dict.Add(valKey, value); } AbsoluteTime expiry = new AbsoluteTime(new TimeSpan(0, 0, 0, Timeoutseconds)); _cacheManager.Add(key, dict, CacheItemPriority.High,null, new ICacheItemExpiration[] { expiry }); } ///
/// 向缓存中更新一个对象。 /// ///
缓存的键值,该值通常是使用缓存机制的方法的名称。 ///
缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。 ///
需要缓存的对象。 public void Put(string key, string valKey, object value) { Add(key, valKey, value,60); } ///
/// 从缓存中读取对象。 /// ///
缓存的键值,该值通常是使用缓存机制的方法的名称。 ///
缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。 ///
被缓存的对象。
public object Get(string key, string valKey) { if (_cacheManager.Contains(key)) { Dictionary
dict = (Dictionary
)_cacheManager[key]; if (dict != null && dict.ContainsKey(valKey)) return dict[valKey]; else return null; } return null; } ///
/// 从缓存中移除对象。 /// ///
缓存的键值,该值通常是使用缓存机制的方法的名称。 public void Remove(string key) { _cacheManager.Remove(key); } ///
/// 获取一个
值,该值表示拥有指定键值的缓存是否存在。 ///
///
指定的键值。 ///
如果缓存存在,则返回true,否则返回false。
public bool Exists(string key) { if (!_cacheManager.Contains(key)) return false; if (_cacheManager[key] == null || (Dictionary
)_cacheManager[key] == null) return false; return true; } ///
/// 获取一个
值,该值表示拥有指定键值和缓存值键的缓存是否存在。 ///
///
指定的键值。 ///
缓存值键。 ///
如果缓存存在,则返回true,否则返回false。
public bool Exists(string key, string valKey) { if (!_cacheManager.Contains(key)) return false; if (_cacheManager[key] == null || (Dictionary
)_cacheManager[key] == null) return false; return _cacheManager.Contains(key) && ((Dictionary
)_cacheManager[key]).ContainsKey(valKey); } #endregion }}
ServiceLocator
 
using Microsoft.Practices.Unity;using Microsoft.Practices.Unity.Configuration;using System;using System.Collections.Generic;using System.Configuration;using System.Linq;using System.Reflection;using System.Text;using System.Threading.Tasks;namespace MvcApplication1{    public sealed class ServiceLocator : IServiceProvider    {        #region Private Fields        private readonly IUnityContainer container;        #endregion        #region Private Static Fields        private static readonly ServiceLocator instance = new ServiceLocator();        #endregion        #region Ctor        ///         /// Initializes a new instance of 
ServiceLocator
class. ///
private ServiceLocator() { UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); container = new UnityContainer(); section.Configure(container); } #endregion #region Public Static Properties /// /// Gets the singleton instance of the
ServiceLocator
class. ///
public static ServiceLocator Instance { get { return instance; } } #endregion #region Private Methods private IEnumerable
GetParameterOverrides(object overridedArguments) { List
overrides = new List
(); Type argumentsType = overridedArguments.GetType(); argumentsType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .ToList() .ForEach(property => { var propertyValue = property.GetValue(overridedArguments, null); var propertyName = property.Name; overrides.Add(new ParameterOverride(propertyName, propertyValue)); }); return overrides; } #endregion #region Public Methods ///
/// Gets the service instance with the given type. /// ///
The type of the service.
///
The service instance.
public T GetService
() { return container.Resolve
(); } ///
/// Gets the service instance with the given type by using the overrided arguments. /// ///
The type of the service.
///
The overrided arguments. ///
The service instance.
public T GetService
(object overridedArguments) { var overrides = GetParameterOverrides(overridedArguments); return container.Resolve
(overrides.ToArray()); } ///
/// Gets the service instance with the given type by using the overrided arguments. /// ///
The type of the service. ///
The overrided arguments. ///
The service instance.
public object GetService(Type serviceType, object overridedArguments) { var overrides = GetParameterOverrides(overridedArguments); return container.Resolve(serviceType, overrides.ToArray()); } #endregion #region IServiceProvider Members ///
/// Gets the service instance with the given type. /// ///
The type of the service. ///
The service instance.
public object GetService(Type serviceType) { return container.Resolve(serviceType); } #endregion }}

使用方法

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MvcApplication1{    public class Talk : ITalk    {        public string Speak(string msg)        {            return msg;        }    }    public interface ITalk    {        [Caching(CachingMethod.Get)]        string Speak(string msg);    }}

 

ITalk talk = ServiceLocator.Instance.GetService
(); string s = talk.Speak("正常调用"); string s1 = talk.Speak("正常调用"); ViewBag.Message = s +"_"+ s1;

只需要在接口中追加[Caching(CachingMethod.Get,60)],缓存就可以使用了,无需写一堆代码。
第一次调用
60秒内刷新

转载于:https://www.cnblogs.com/kfsmqoo/p/4242345.html

你可能感兴趣的文章
使用 JointCode.Shuttle 访问任意 AppDomain 的服务
查看>>
hdoj 1846 Brave Game(巴什博弈)
查看>>
Round #345 B. Beautiful Paintings(Div.2)
查看>>
51nod 1018排序
查看>>
sqlite的坑
查看>>
digitalocean --- How To Install Apache Tomcat 8 on Ubuntu 16.04
查看>>
linux swoole
查看>>
An Easy Problem?! - POJ 2826(求面积)
查看>>
【题解】[P4178 Tree]
查看>>
Jquery ui widget开发
查看>>
css3实现循环执行动画,且动画每次都有延迟
查看>>
更改git仓库地址
查看>>
有标号DAG计数 [容斥原理 子集反演 组合数学 fft]
查看>>
Recipe 1.4. Reversing a String by Words or Characters
查看>>
Rule 1: Make Fewer HTTP Requests(Chapter 1 of High performance Web Sites)
查看>>
sql注入
查看>>
「破解」Xposed强
查看>>
Linux 平台下 MySQL 5.5 安装 说明 与 示例
查看>>
src与href的区别
查看>>
ABAP工作区,内表,标题行的定义和区别
查看>>