博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Unity--Apwork框架】AOP编程--拦截,用于缓存和异常处理(Unity框架的拦截注入-Interception)...
阅读量:4489 次
发布时间:2019-06-08

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

第一步:定义拦截行为:CachingBehavior 和 ExceptionLoggingBehavior

           他们都继承接口:IInterceptionBehavior (程序集 Microsoft.Practices.Unity.Interception.dll, v2.1.505.0

                                                                  命名空间:Microsoft.Practices.Unity.InterceptionExtension)

           需要实现连个接口:

public IEnumerable
GetRequiredInterfaces()public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)

 

CachingBehavior.cs

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Keasy5.Infrastructure.Caching;using Microsoft.Practices.Unity.InterceptionExtension;namespace Keasy5.Infrastructure.InterceptionBehaviors{    ///     /// 表示用于方法缓存功能的拦截行为。    ///     public class CachingBehavior : IInterceptionBehavior    {        #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 #region IInterceptionBehavior Members /// /// 获取当前行为需要拦截的对象类型接口。 /// ///
所有需要拦截的对象类型接口。
public IEnumerable
GetRequiredInterfaces() { return Type.EmptyTypes; } ///
/// 通过实现此方法来拦截调用并执行所需的拦截行为。 /// ///
调用拦截目标时的输入信息。 ///
通过行为链来获取下一个拦截行为的委托。 ///
从拦截目标获得的返回信息。
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); 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) { 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; } } return getNext().Invoke(input, getNext); } ///
/// 获取一个
值,该值表示当前拦截行为被调用时,是否真的需要执行 /// 某些操作。 ///
public bool WillExecute { get { return true; } } #endregion }}
View Code

 

ExceptionLoggingBehavior.cs

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Microsoft.Practices.Unity.InterceptionExtension;namespace Keasy5.Infrastructure.InterceptionBehaviors{    ///     /// 表示用于异常日志记录的拦截行为。    ///     public class ExceptionLoggingBehavior : IInterceptionBehavior    {        #region IInterceptionBehavior Members        ///         /// 获取当前行为需要拦截的对象类型接口。        ///         /// 
所有需要拦截的对象类型接口。
public IEnumerable
GetRequiredInterfaces() { return Type.EmptyTypes; } ///
/// 通过实现此方法来拦截调用并执行所需的拦截行为。 /// ///
调用拦截目标时的输入信息。 ///
通过行为链来获取下一个拦截行为的委托。 ///
从拦截目标获得的返回信息。
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { var methodReturn = getNext().Invoke(input, getNext); if (methodReturn.Exception != null) { Utils.Log(methodReturn.Exception); } return methodReturn; } ///
/// 获取一个
值,该值表示当前拦截行为被调用时,是否真的需要执行 /// 某些操作。 ///
public bool WillExecute { get { return true; } } #endregion }}
View Code

 

第二步:添加配置文件,为需要被拦截的类添加拦截行为。

例如如下的配置,是为实现了接口

Keasy5.ServiceContract.IProductService

的类的所以方法添加拦截行为。

web/app.config文件:

。。。。。
。。。。

 

比如:对于ExceptionLoggingBehavior的拦截行为作用于IProductService接口的实现类的所有方法:

///         /// 通过实现此方法来拦截调用并执行所需的拦截行为。        ///         /// 调用拦截目标时的输入信息。        /// 通过行为链来获取下一个拦截行为的委托。        /// 
从拦截目标获得的返回信息。
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { var methodReturn = getNext().Invoke(input, getNext); if (methodReturn.Exception != null) { Utils.Log(methodReturn.Exception); } return methodReturn; }

效果是:如果IProductService接口的实现类的所有方法如果抛出了异常,将调用   

Utils.Log(methodReturn.Exception);

将异常信息写入日志系统(这就是我们进行拦截的目的)。

 

------------------------------------------------

对应缓存CachingBehavior的拦截的补充:

第一:定义特性:CachingAttribute

CachingAttribute.cs

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

 

第二:将特性CachingAttribute应用于IProductService的接口方法:

using System;using System.Collections.Generic;using System.Linq;using System.ServiceModel;using System.Text;using System.Threading.Tasks;using ByteartRetail.DataObjects;using Keasy5.DataObject;using Keasy5.Infrastructure;using Keasy5.Infrastructure.Caching;namespace Keasy5.ServiceContract{    ///     /// 表示与“商品”相关的应用层服务契约。    ///     [ServiceContract(Namespace = "http://www.ByteartRetail.com")]    public interface IProductService : IApplicationServiceContract    {        #region Methods        ///         /// 创建商品信息。        ///         /// 需要创建的商品信息。        /// 
已创建的商品信息。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Remove, "GetProductsForCategory", "GetProductsWithPagination", "GetFeaturedProducts", "GetProductsForCategoryWithPagination", "GetProducts", "GetProductByID")] ProductDataObjectList CreateProducts(ProductDataObjectList productDataObjects); /// /// 创建商品分类。 /// /// 需要创建的商品分类。 ///
已创建的商品分类。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Remove, "GetCategories")] CategoryDataObjectList CreateCategories(CategoryDataObjectList categoryDataObjects); /// /// 更新商品信息。 /// /// 需要更新的商品信息。 ///
已更新的商品信息。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Remove, "GetProductsForCategory", "GetProductsWithPagination", "GetFeaturedProducts", "GetProductsForCategoryWithPagination", "GetProducts", "GetProductByID")] ProductDataObjectList UpdateProducts(ProductDataObjectList productDataObjects); /// /// 更新商品分类。 /// /// 需要更新的商品分类。 ///
已更新的商品分类。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Remove, "GetCategories", "GetCategoryByID")] CategoryDataObjectList UpdateCategories(CategoryDataObjectList categoryDataObjects); /// /// 删除商品信息。 /// /// 需要删除的商品信息的ID值。 [OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Remove, "GetProductsForCategory", "GetProductsWithPagination", "GetFeaturedProducts", "GetProductsForCategoryWithPagination", "GetProducts", "GetProductByID")] void DeleteProducts(IDList productIDs); /// /// 删除商品分类。 /// /// 需要删除的商品分类的ID值。 [OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Remove, "GetCategories", "GetCategoryByID")] void DeleteCategories(IDList categoryIDs); /// /// 设置商品分类。 /// /// 需要进行分类的商品ID值。 /// 商品分类ID值。 ///
带有商品分类信息的对象。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Remove, "GetProductsForCategory", "GetProductsForCategoryWithPagination")] CategorizationDataObject CategorizeProduct(Guid productID, Guid categoryID); /// /// 取消商品分类。 /// /// 需要取消分类的商品ID值。 [OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Remove, "GetProductsForCategory", "GetProductsForCategoryWithPagination")] void UncategorizeProduct(Guid productID); /// /// 根据指定的ID值获取商品分类。 /// /// 商品分类ID值。 /// 查询方式。 ///
商品分类。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Get)] CategoryDataObject GetCategoryByID(Guid id, QuerySpec spec); /// /// 获取所有的商品分类。 /// /// 查询方式。 ///
所有的商品分类。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Get)] CategoryDataObjectList GetCategories(QuerySpec spec); /// /// 根据指定的ID值获取商品信息。 /// /// 商品信息ID值。 /// 查询方式。 ///
商品信息。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Get)] ProductDataObject GetProductByID(Guid id, QuerySpec spec); /// /// 获取所有的商品信息。 /// /// 查询方式。 ///
商品信息。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Get)] ProductDataObjectList GetProducts(QuerySpec spec); /// /// 以分页的方式获取所有商品信息。 /// /// 带有分页参数信息的对象。 ///
经过分页的商品信息。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Get)] ProductDataObjectListWithPagination GetProductsWithPagination(Pagination pagination); /// /// 根据指定的商品分类ID值,获取该分类下所有的商品信息。 /// /// 商品分类ID值。 ///
所有的商品信息。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Get)] ProductDataObjectList GetProductsForCategory(Guid categoryID); /// /// 根据指定的商品分类ID值,以分页的方式获取该分类下所有的商品信息。 /// /// 商品分类ID值。 /// 带有分页参数信息的对象。 ///
所有的商品信息。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Get)] ProductDataObjectListWithPagination GetProductsForCategoryWithPagination(Guid categoryID, Pagination pagination); /// /// 获取所有的特色商品信息。 /// /// 需要获取的特色商品信息的个数。 ///
特色商品信息。
[OperationContract] [FaultContract(typeof(FaultData))] [Caching(CachingMethod.Get)] ProductDataObjectList GetFeaturedProducts(int count); #endregion }}
View Code

 

第三:拦截IProductService接口的实现类的所有方法的所有方法,

并通过CachingAttribute特性进行方法 的筛选,

还进一步根据CachingAttribute的属性值进行一步的处理:

CachingBehavior .cs

///         /// 通过实现此方法来拦截调用并执行所需的拦截行为。        ///         /// 调用拦截目标时的输入信息。        /// 通过行为链来获取下一个拦截行为的委托。        /// 
从拦截目标获得的返回信息。
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); 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) { 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; } } return getNext().Invoke(input, getNext); }

 

--------------------------------

unity服务定位器:ServiceLocator

ServiceLocator.cs 

using System;using System.Collections.Generic;using System.Configuration;using System.Linq;using System.Reflection;using System.Text;using Microsoft.Practices.Unity;using Microsoft.Practices.Unity.Configuration;namespace Keasy5.Infrastructure{    ///     /// Represents the Service Locator.    ///     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
(); } public IEnumerable
ResolveAll
() { return container.ResolveAll
(); } ///
/// 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 }}
View Code

 

 

 

 

转载于:https://www.cnblogs.com/easy5weikai/p/3790931.html

你可能感兴趣的文章
jQuery 遍历--siblings() 方法、each() 方法
查看>>
window系统下调度数据库类型资源库中的kettle job
查看>>
10、小易记单词--2017网易春招
查看>>
monkey 命令详解
查看>>
Scrapy XPath语法
查看>>
图像预处理
查看>>
16个Web开发的IDE
查看>>
Oracle KEEP的用法
查看>>
Java动态代理与Cglib库
查看>>
Hebbian学习规则 1神经元 简单实现
查看>>
libevent源码深度剖析一
查看>>
SSH隧道技术简介
查看>>
PAT乙级1025
查看>>
找的好网站(macdow语法,扫描二维码,)
查看>>
浏览器插件开发遇到的问题
查看>>
JS之正则表达式
查看>>
EF Core 1.0 和 SQLServer 2008 分页的问题
查看>>
BZOJ1798: [Ahoi2009]Seq 维护序列seq
查看>>
PS--人物黄金色调
查看>>
开启ucosii的移植之旅
查看>>