首页 / 缓存 / Unity实现AOP(用于实现缓存)
Unity实现AOP(用于实现缓存)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Unity实现AOP(用于实现缓存),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含16109字,纯文字阅读大概需要24分钟。
内容图文
先下载这个NUGET包。
个人理解UINITY是在IOC上实现的AOP(自己试验了好多次),所以先定义接口跟实现类。
namespace Cache { public class Talk : ITalk { [Caching(CachingMethod.Get)] public System.Collections.Generic.List<string> GetData() { Data.UpData(); return Data.GetData(); } } } namespace Cache { publicinterface ITalk { [Caching(CachingMethod.Get)] List<string> GetData(); } }
然后写CachingAttribute特性类。实际上所有ITalk的实现都会被拦截,所以写了一个特性来筛选。
[AttributeUsage(AttributeTargets.Method,AllowMultiple = false,Inherited = false)] publicclass CachingAttribute:Attribute { ///<summary>/// 初始化一个新的<c>CachingAttribute</c>类型。 ///</summary>///<param name="method">缓存方式。</param>public CachingAttribute(CachingMethod method) { Method = method; } ///<summary>/// 初始化一个新的<c>CachingAttribute</c>类型。 ///</summary>///<param name="method">缓存方式。</param>///<param name="correspondingMethodNames">/// 与当前缓存方式相关的方法名称。注:此参数仅在缓存方式为Remove时起作用。 ///</param>public CachingAttribute(CachingMethod method, paramsstring[] correspondingMethodNames) : this(method) { CorrespondingMethodNames = correspondingMethodNames; } #region Public Properties ///<summary>/// 获取或设置缓存方式。 ///</summary>public CachingMethod Method { get; set; } ///<summary>/// 获取或设置一个<see cref="Boolean"/>值,该值表示当缓存方式为Put时,是否强制将值写入缓存中。 ///</summary>publicbool Force { get; set; } ///<summary>/// 获取或设置与当前缓存方式相关的方法名称。注:此参数仅在缓存方式为Remove时起作用。 ///</summary>publicstring[] CorrespondingMethodNames { get; set; } #endregion }
枚举
public enum CachingMethod { Get, Put, Remove }
缓存机制接口
/// <summary> /// 表示实现该接口的类型是能够为应用程序提供缓存机制的类型。 /// </summary> public interface ICacheProvider { #region Methods ///<summary>/// 向缓存中添加一个对象。 ///</summary>///<param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>///<param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>///<param name="value">需要缓存的对象。</param>void Add(string key, string valKey, object value); ///<summary>/// 向缓存中更新一个对象。 ///</summary>///<param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>///<param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>///<param name="value">需要缓存的对象。</param>void Put(string key, string valKey, object value); ///<summary>/// 从缓存中读取对象。 ///</summary>///<param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>///<param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>///<returns>被缓存的对象。</returns>object Get(string key, string valKey); ///<summary>/// 从缓存中移除对象。 ///</summary>///<param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>void Remove(string key); ///<summary>/// 获取一个<see cref="Boolean"/>值,该值表示拥有指定键值的缓存是否存在。 ///</summary>///<param name="key">指定的键值。</param>///<returns>如果缓存存在,则返回true,否则返回false。</returns>bool Exists(string key); ///<summary>/// 获取一个<see cref="Boolean"/>值,该值表示拥有指定键值和缓存值键的缓存是否存在。 ///</summary>///<param name="key">指定的键值。</param>///<param name="valKey">缓存值键。</param>///<returns>如果缓存存在,则返回true,否则返回false。</returns>bool Exists(string key, string valKey); #endregion }
两种方式的缓存接口实现
/// <summary> /// 表示基于AppFabric的缓存机制的实现。 /// </summary> public class AppfabricCacheProvider : ICacheProvider { private readonly DataCacheFactory factory = new DataCacheFactory(); privatereadonly DataCache cache; public AppfabricCacheProvider() { cache = factory.GetDefaultCache(); } #region ICacheProvider Members publicvoid Add(string key, string valKey, object value) { Dictionary<string, object> val = (Dictionary<string, object>)cache.Get(key); if (val == null) { val = new Dictionary<string, object>(); val.Add(valKey, value); cache.Add(key, val); } else { if (!val.ContainsKey(valKey)) val.Add(valKey, value); else val[valKey] = value; cache.Put(key, val); } } publicvoid Put(string key, string valKey, object value) { Add(key, valKey, value); } publicobject Get(string key, string valKey) { if (Exists(key, valKey)) { return ((Dictionary<string, object>)cache.Get(key))[valKey]; } returnnull; } publicvoid Remove(string key) { cache.Remove(key); } publicbool Exists(string key) { return cache.Get(key) != null; } publicbool Exists(string key, string valKey) { var val = cache.Get(key); if (val == null) returnfalse; return ((Dictionary<string, object>)val).ContainsKey(valKey); } #endregion }
/// <summary> /// 表示基于Microsoft Patterns & Practices - Enterprise Library Caching Application Block的缓存机制的实现。 /// </summary> public class EntLibCacheProvider : ICacheProvider { #region Private Fields privatereadonly ICacheManager cacheManager = CacheFactory.GetCacheManager(); #endregion#region ICacheProvider Members ///<summary>/// 向缓存中添加一个对象。 ///</summary>///<param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>///<param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>///<param name="value">需要缓存的对象。</param>publicvoid Add(string key, string valKey, object value) { Dictionary<string, object> dict = null; if (cacheManager.Contains(key)) { dict = (Dictionary<string, object>)cacheManager[key]; dict[valKey] = value; } else { dict = new Dictionary<string, object>(); dict.Add(valKey, value); } cacheManager.Add(key, dict); } ///<summary>/// 向缓存中更新一个对象。 ///</summary>///<param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>///<param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>///<param name="value">需要缓存的对象。</param>publicvoid Put(string key, string valKey, object value) { Add(key, valKey, value); } ///<summary>/// 从缓存中读取对象。 ///</summary>///<param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>///<param name="valKey">缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。</param>///<returns>被缓存的对象。</returns>publicobject Get(string key, string valKey) { if (cacheManager.Contains(key)) { Dictionary<string, object> dict = (Dictionary<string, object>)cacheManager[key]; if (dict != null && dict.ContainsKey(valKey)) return dict[valKey]; elsereturnnull; } returnnull; } ///<summary>/// 从缓存中移除对象。 ///</summary>///<param name="key">缓存的键值,该值通常是使用缓存机制的方法的名称。</param>publicvoid Remove(string key) { cacheManager.Remove(key); } ///<summary>/// 获取一个<see cref="Boolean"/>值,该值表示拥有指定键值的缓存是否存在。 ///</summary>///<param name="key">指定的键值。</param>///<returns>如果缓存存在,则返回true,否则返回false。</returns>publicbool Exists(string key) { return cacheManager.Contains(key); } ///<summary>/// 获取一个<see cref="Boolean"/>值,该值表示拥有指定键值和缓存值键的缓存是否存在。 ///</summary>///<param name="key">指定的键值。</param>///<param name="valKey">缓存值键。</param>///<returns>如果缓存存在,则返回true,否则返回false。</returns>publicbool Exists(string key, string valKey) { return cacheManager.Contains(key) && ((Dictionary<string, object>)cacheManager[key]).ContainsKey(valKey); } #endregion }
CacheManager用来管理缓存实现( public ICacheProvider CacheProvider = new EntLibCacheProvider();这里可以应该用依赖注入,因为测试懒得写了就直接实例化了)
public class CacheManager : ICacheProvider { public ICacheProvider CacheProvider = new EntLibCacheProvider(); // ReSharper disable once InconsistentNamingprivate CacheManager instance = new CacheManager(); static CacheManager() { } #region 公共属性 ///<summary>/// 获取<c>CacheManager</c>类型的单件(Singleton)实例。 ///</summary>public CacheManager Instance { get { return instance; } } #endregionpublicvoid Add(string key, string valKey, object value) { CacheProvider.Add(key, valKey, value); } publicvoid Put(string key, string valKey, object value) { CacheProvider.Put(key, valKey, value); } publicobject Get(string key, string valKey) { return CacheProvider.Get(key, valKey); } publicvoid Remove(string key) { CacheProvider.Remove(key); } publicbool Exists(string key) { return CacheProvider.Exists(key); } publicbool Exists(string key, string valKey) { return CacheProvider.Exists(key, valKey); } }
AOP拦截。getNext().Invoke(input, getNext)这一句相当于获取被拦截方法的返回值
public class CachingBehavior : IInterceptionBehavior { /// <summary> /// 根据指定的 <see cref="CachingAttribute"/> 以及 <see cref="IMethodInvocation"/> 实例, /// 获取与某一特定参数值相关的键名。 /// </summary> /// <param name="cachingAttribute"><see cref="CachingAttribute"/> 实例。 </param> /// <param name="input"><see cref="IMethodInvocation"/> 实例。 </param> /// <returns> 与某一特定参数值相关的键名。 /// <remarks> /// 例如: <see cref="ICacheProvider.Add"/> /// </remarks> /// </returns> private string GetValueKey(CachingAttribute cachingAttribute, IMethodInvocation input) { switch (cachingAttribute.Method) { case CachingMethod.Remove: return null ; 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: thrownew InvalidOperationException("无效的缓存方式。"); } } ///<summary>/// 获取当前行为需要拦截的对象类型接口。 ///</summary>///<returns>所有需要拦截的对象类型接口。</returns>public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } ///<summary>/// 通过实现此方法来拦截调用并执行所需的拦截行为。 ///</summary>///<param name="input">调用拦截目标时的输入信息。</param>///<param name="getNext">通过行为链来获取下一个拦截行为的委托。</param>///<returns>从拦截目标获得的返回信息。</returns>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 (new CacheManager().Instance.Exists(key, valKey)) { var obj = new CacheManager().Instance.Get(key, valKey); var arguments = newobject[input.Arguments.Count]; input.Arguments.CopyTo(arguments, 0); returnnew VirtualMethodReturn(input, obj, arguments); } var methodReturn = getNext().Invoke(input, getNext); if (methodReturn.Exception == null) { new 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 (new CacheManager().Instance.Exists(key)) { if (cachingAttribute.Force) { new CacheManager().Instance.Remove(key); new CacheManager().Instance.Add(key, valKey, methodReturn.ReturnValue); } elsenew CacheManager().Instance.Put(key, valKey, methodReturn.ReturnValue); } elsenew CacheManager().Instance.Add(key, valKey, methodReturn.ReturnValue); return methodReturn; } catch (Exception ex) { returnnew VirtualMethodReturn(input, ex); } case CachingMethod.Remove: try { var removeKeys = cachingAttribute.CorrespondingMethodNames; foreach (var removeKey in removeKeys) { if (new CacheManager().Instance.Exists(removeKey)) new CacheManager().Instance.Remove(removeKey); } var methodReturn = getNext().Invoke(input, getNext); return methodReturn; } catch (Exception ex) { returnnew VirtualMethodReturn(input, ex); } } } return getNext().Invoke(input, getNext); } ///<summary>/// 获取一个<see cref="Boolean"/>值,该值表示当前拦截行为被调用时,是否真的需要执行 /// 某些操作。 ///</summary>publicbool WillExecute { get { returntrue; } } }
Unity操作类
/// <summary> /// Represents the Service Locator. /// </summary> public sealed class ServiceLocator : IServiceProvider { #region Private Fields privatereadonly IUnityContainer container; #endregion#region Private Static Fields privatestaticreadonly ServiceLocator instance = new ServiceLocator(); #endregion#region Ctor ///<summary>/// Initializes a new instance of <c>ServiceLocator</c> class. ///</summary>private ServiceLocator() { UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); container = new UnityContainer(); section.Configure(container); } #endregion#region Public Static Properties ///<summary>/// Gets the singleton instance of the <c>ServiceLocator</c> class. ///</summary>publicstatic ServiceLocator Instance { get { return instance; } } #endregion#region Private Methods private IEnumerable<ParameterOverride> GetParameterOverrides(object overridedArguments) { List<ParameterOverride> overrides = new List<ParameterOverride>(); 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 ///<summary>/// Gets the service instance with the given type. ///</summary>///<typeparam name="T">The type of the service.</typeparam>///<returns>The service instance.</returns>public T GetService<T>() { return container.Resolve<T>(); } ///<summary>/// Gets the service instance with the given type by using the overrided arguments. ///</summary>///<typeparam name="T">The type of the service.</typeparam>///<param name="overridedArguments">The overrided arguments.</param>///<returns>The service instance.</returns>public T GetService<T>(object overridedArguments) { var overrides = GetParameterOverrides(overridedArguments); return container.Resolve<T>(overrides.ToArray()); } ///<summary>/// Gets the service instance with the given type by using the overrided arguments. ///</summary>///<param name="serviceType">The type of the service.</param>///<param name="overridedArguments">The overrided arguments.</param>///<returns>The service instance.</returns>publicobject GetService(Type serviceType, object overridedArguments) { var overrides = GetParameterOverrides(overridedArguments); return container.Resolve(serviceType, overrides.ToArray()); } #endregion#region IServiceProvider Members ///<summary>/// Gets the service instance with the given type. ///</summary>///<param name="serviceType">The type of the service.</param>///<returns>The service instance.</returns>publicobject GetService(Type serviceType) { return container.Resolve(serviceType); } #endregion }
最后需要在配置文件中配置一下。
<configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" /> </configSections> <!--BEGIN: Unity--> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" /> <container> <extension type="Interception" /> <!--Cache Provider--> <register type="Cache.ITalk, Cache" mapTo="Cache.Talk, Cache"> <interceptor type="InterfaceInterceptor" /> <interceptionBehavior type="Cache.CachingBehavior, Cache" /> </register> </container> </unity> <!--END: Unity-->
https://github.com/dxka8/AopWeb 代码
经测试AOP已经实现,但是两个缓存实现因为用的第三方还在报错(自己实现一个也可),正在踏坑(有懂的同学可以支援一下我啊)。
注明:非原创,在dax.net的APWORKS里面扒的。
原文:http://www.cnblogs.com/harpz/p/4201585.html
内容总结
以上是互联网集市为您收集整理的Unity实现AOP(用于实现缓存)全部内容,希望文章能够帮你解决Unity实现AOP(用于实现缓存)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。