你的位置:首页 > 软件开发 > ASP.net > [.NET领域驱动设计实战系列]专题九:DDD案例:网上书店AOP和站点地图的实现

[.NET领域驱动设计实战系列]专题九:DDD案例:网上书店AOP和站点地图的实现

发布时间:2015-06-23 00:00:04
一、引言   在前面一专题介绍到,要让缓存生效还需要实现对AOP(面向切面编程)的支持。所以本专题将介绍了网上书店案例中AOP的实现。关于AOP的概念,大家可以参考文章:http://www.cnblogs.com/jin-yuan/p/3811077.html。这里我简单介 ...

[.NET领域驱动设计实战系列]专题九:DDD案例:网上书店AOP和站点地图的实现

一、引言

   在前面一专题介绍到,要让缓存生效还需要实现对AOP(面向切面编程)的支持。所以本专题将介绍了网上书店案例中AOP的实现。关于AOP的概念,大家可以参考文章:http://www.cnblogs.com/jin-yuan/p/3811077.html。这里我简单介绍下AOP:AOP可以理解为对方法进行截获,这样就可以在方法调用前或调用后插入需要的逻辑。例如可以在方法调用前,加入缓存查找逻辑等。这里缓存查找逻辑就在方法调用前被执行。通过对AOP的支持,每个方法就可以分为3部分了,方法调用前逻辑->具体需要调用的方法->方法调用后的逻辑。也就是在方法调用的时候“切了一刀”。

二、网上书店AOP的实现

  你可以从零开始去实现AOP,但是目前已经存在很多AOP框架了,所以在本案例中将直接通过Unity的AOP框架(Unity.Interception)来实现网上书店对AOP的支持。通常AOP的实现放在基础设施层进行实现,因为可能其他所有层都需要加入对AOP的支持。本案例中将对两个方面的AOP进行实现,一个是方法调用前缓存的记录或查找,另一个是方法调用后异常信息的记录。在实现具体代码之前,我们需要在基础设施层通过Nuget来引入Unity.Interception包。添加成功之后,我们需要定义两个类分别去实现AOP框架中IInterceptionBehavior接口。由于本案例中需要对缓存和异常日志功能进行AOP实现,自然就需要定义CachingBehavior和ExceptionLoggingBehavior两个类去实现IInterceptionBehavior接口。首先让我们看看CachingBehavior类的实现,具体实现代码如下所示:

 // 缓存AOP的实现  public class CachingBehavior : IInterceptionBehavior  {    private readonly ICacheProvider _cacheProvider;    public CachingBehavior()    {      _cacheProvider = ServiceLocator.Instance.GetService<ICacheProvider>();    }    // 生成缓存值的键值    private string GetValueKey(CacheAttribute cachingAttribute, IMethodInvocation input)    {      switch (cachingAttribute.Method)      {        // 如果是Remove,则不存在特定值键名,所有的以该方法名称相关的缓存都需要清除        case CachingMethod.Remove:          return null;        // 如果是Get或者Update,则需要产生一个针对特定参数值的键名        case CachingMethod.Get:        case CachingMethod.Update:          if (input.Arguments != null &&            input.Arguments.Count > 0)          {            var sb = new StringBuilder();            for (var i = 0; i < input.Arguments.Count; i++)            {              sb.Append(input.Arguments[i]);              if (i != input.Arguments.Count - 1)                sb.Append("_");            }            return sb.ToString();          }          else            return "NULL";        default:          throw new InvalidOperationException("无效的缓存方式。");      }    }    #region IInterceptionBehavior Members    public IEnumerable<Type> GetRequiredInterfaces()    {      return Type.EmptyTypes;    }    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)    {      // 获得被拦截的方法      var method = input.MethodBase;      var key = method.Name; // 获得拦截的方法名      // 如果拦截的方法定义了Cache属性,说明需要对该方法的结果需要进行缓存      if (!method.IsDefined(typeof (CacheAttribute), false))         return getNext().Invoke(input, getNext);      var cachingAttribute = (CacheAttribute)method.GetCustomAttributes(typeof (CacheAttribute), false)[0];      var valueKey = GetValueKey(cachingAttribute, input);      switch (cachingAttribute.Method)      {        case CachingMethod.Get:          try          {            // 如果缓存中存在该键值的缓存,则直接返回缓存中的结果退出            if (_cacheProvider.Exists(key, valueKey))            {              var value = _cacheProvider.Get(key, valueKey);              var arguments = new object[input.Arguments.Count];              input.Arguments.CopyTo(arguments, 0);              return new VirtualMethodReturn(input, value, arguments);            }            else // 否则先调用方法,再把返回结果进行缓存            {              var methodReturn = getNext().Invoke(input, getNext);              _cacheProvider.Add(key, valueKey, methodReturn.ReturnValue);              return methodReturn;            }          }          catch (Exception ex)          {            return new VirtualMethodReturn(input, ex);          }        case CachingMethod.Update:          try          {            var methodReturn = getNext().Invoke(input, getNext);            if (_cacheProvider.Exists(key))            {              if (cachingAttribute.IsForce)              {                _cacheProvider.Remove(key);                _cacheProvider.Add(key, valueKey, methodReturn.ReturnValue);              }              else                _cacheProvider.Update(key, valueKey, methodReturn);            }            else              _cacheProvider.Add(key, valueKey, 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 (_cacheProvider.Exists(removeKey))                _cacheProvider.Remove(removeKey);            }             // 执行具体截获的方法            var methodReturn = getNext().Invoke(input, getNext);            return methodReturn;          }          catch (Exception ex)          {            return new VirtualMethodReturn(input, ex);          }        default: break;      }      return getNext().Invoke(input, getNext);    }    public bool WillExecute    {      get { return true; }    }    #endregion   }

原标题:[.NET领域驱动设计实战系列]专题九:DDD案例:网上书店AOP和站点地图的实现

关键词:.NET

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。