热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【UnityApwork框架】AOP编程拦截,用于缓存和异常处理(Unity框架的拦截注入Interception)...

第一步:定义拦截行为:CachingBehavior和ExceptionLoggingBehavior他们都继承接口:IIntercept

第一步:定义拦截行为: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 ){sb.Append(input.Arguments[i].ToString());if (i != input.Arguments.Count - 1)sb.Append("_");}return sb.ToString();}elsereturn "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);}elseCacheManager.Instance.Put(key, valKey, methodReturn.ReturnValue);}elseCacheManager.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文件:

"http://schemas.microsoft.com/practices/2010/unity">"Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />"Interception" />
。。。。。
"Keasy5.ServiceContract.IProductService, Keasy5.ServiceContract" mapTo="Keasy5.Application.Implementation.ProductServiceImpl, Keasy5.Application">"InterfaceInterceptor" />"Keasy5.Infrastructure.InterceptionBehaviors.CachingBehavior, Keasy5.Infrastructure" />"Keasy5.Infrastructure.InterceptionBehaviors.ExceptionLoggingBehavior, Keasy5.Infrastructure" />。。。。

 

比如:对于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);}elseCacheManager.Instance.Put(key, valKey, methodReturn.ReturnValue);}elseCacheManager.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 Fieldsprivate readonly IUnityContainer container;#endregion#region Private Static Fieldsprivate 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 Methodsprivate 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



推荐阅读
author-avatar
做普通的自我
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有