运用Unity结合PolicyInjection实现拦截器[结合操作日志实例]

上一篇文章我们通过Unity自身Unity.InterceptionExtension.IInterceptionBehavior实现一个有系统关异常日志记录;解决代码中到处充满的异常记录的代码;

本文则是通过Unity.InterceptionExtension.ICallHandler实现一个操作日志记录功能;在相应操作方法上通过特性Attribute把操作日志进行统一处理;若想了解Unity依赖注入及AOP功能可以查看先前其它文章;

1:首先我们在公共助手层Command层新建OperateLogCallHandler类及OperateLogAttribute类

其中类OperateLogCallHandler继承自ICallHandler,并且我们定义的属性(MessageInfo,ShowThrow),此处我们只是简单的显示出操作内容信息,若实际项目可以对下面进行简单修改便可,比如写入日志、数据库等;代码result.Exception == null则表示执行代码没有出现异常才逻辑写入

using Microsoft.Practices.Unity.InterceptionExtension;

namespace Command
{
    public class OperateLogCallHandler:ICallHandler
    {
        public string _messageInfo { set; get; }

        public bool _showThrow { get; set; }
        
        private int _order = 0;

        public OperateLogCallHandler(string MessageInfo, bool ShowThrow)
        {
            this._messageInfo = MessageInfo;
            this._showThrow = ShowThrow;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            if (input == null) throw new ArgumentNullException("input");
            if (getNext == null) throw new ArgumentNullException("getNext");

            var result = getNext()(input, getNext);
            if (result.Exception == null)
            {
                //进行逻辑代码编写  比如把操作内容写入数据库
                Console.WriteLine("操作的内容为:" + _messageInfo);
            }
            if (_showThrow) result.Exception = null;
            return result;
        }

        public int Order
        {
            get
            {
                return _order;
            }
            set
            {
                _order = value;
            }
        }
    }
}

而类OperateLogAttribute则继承自HandlerAttribute,并且我们设定此特性只能作用于方法上;

using Microsoft.Practices.Unity.InterceptionExtension;
namespace Command
{
    [AttributeUsage(AttributeTargets.Method)]
    public class OperateLogAttribute : HandlerAttribute
    {
        public string messageInfo { get; set; }

        public bool showThrow { get; set; }

        public OperateLogAttribute()
        {
 
        }

        public OperateLogAttribute(string MessagInfo, bool ShowThrow)
        {
            this.messageInfo = MessagInfo;
            this.showThrow = ShowThrow;
        }

        public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
        {
            OperateLogCallHandler handler = new OperateLogCallHandler(this.messageInfo, this.showThrow);
            handler.Order = this.Order;
            return handler;
        }
    }
}

2:公共层里还有一个助手类UnityContainerHelp,用于读取加载配置

using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity.InterceptionExtension.Configuration;
using System.Configuration;
using System.Reflection;

namespace Command
{
    public class UnityContainerHelp
    {
        private IUnityContainer container;
        public UnityContainerHelp()
        {
            container = new UnityContainer();
            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            container.LoadConfiguration(section, "FirstClass");
        }

        public T GetServer<T>()
        {
            return container.Resolve<T>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ConfigName">配置文件中指定的文字</param>
        /// <returns></returns>
        public T GetServer<T>(string ConfigName)
        {
            return container.Resolve<T>(ConfigName);
        }

        /// <summary>
        /// 返回构结函数带参数
        /// </summary>
        /// <typeparam name="T">依赖对象</typeparam>
        /// <param name="parameterList">参数集合(参数名,参数值)</param>
        /// <returns></returns>
        public T GetServer<T>(Dictionary<string, object> parameterList)
        {
            var list = new ParameterOverrides();
            foreach (KeyValuePair<string, object> item in parameterList)
            {
                list.Add(item.Key, item.Value);
            }
            return container.Resolve<T>(list);
        }
        /// <summary>
        /// 返回构结函数带参数
        /// </summary>
        /// <typeparam name="T">依赖对象</typeparam>
        /// <param name="ConfigName">配置文件中指定的文字(没写会报异常)</param>
        /// <param name="parameterList">参数集合(参数名,参数值)</param>
        /// <returns></returns>
        public T GetServer<T>(string ConfigName,Dictionary<string,object> parameterList)
        {
            var list = new ParameterOverrides();
            foreach (KeyValuePair<string, object> item in parameterList) 
            {
                list.Add(item.Key, item.Value);
            }
            return container.Resolve<T>(ConfigName,list);
        }
    }
}

3:接着在接口层相应的方法上使用我们刚才创建的特性,注意必需引用Microsoft.Practices.Unity.InterceptionExtension.dll;若则特性将会找不到

using Microsoft.Practices.Unity.InterceptionExtension;
using Command;
namespace IAopBLL
{
    public interface IUser
    {
        [OperateLog(Order = 10, messageInfo = "增加用户", showThrow = true)]
        void CreateUser();

        [OperateLog(Order = 10, messageInfo = "编辑用户", showThrow = true)]
        void UpdateUser();
    }
}

4:在BLL层里实现上面的接口,在方法里面我们就不进行任何操作

using IAopDAL;
using IAopBLL;
using Command;
namespace AopBLL
{
    public class UserBLL:IUser
    {
        public void CreateUser()
        {
            //逻辑代码,此处为了简单就省略不写
        }

        public void UpdateUser()
        {
            //逻辑代码,此处为了简单就省略不写
        }
    }
}

5:下面为主程序调用代码,这里我们简单运用到Unity依赖注入代码

using IAopBLL;
using Command;
namespace AopUnity
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("-----------------------------------");
            IUser bllProperty = new UnityContainerHelp().GetServer<IUser>("UserBllAop");
            bllProperty.CreateUser();
            bllProperty.UpdateUser();
            Console.WriteLine("-----------------------------------");
        }
    }
}

配置文件的内容如下:其中有两个比较要注意的地方(a处 name="UserBllAop" 主程序里有调用 b处 <policyInjection/>拦载器才会起作用)

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practces/2010/unity">
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
    <container name="FirstClass">
      <extension type="Interception"/>
      <register type="IAopBLL.IUser,IAopBLL" mapTo="AopBLL.UserBLL,AopBLL" name="UserBllAop">
        <interceptor type="InterfaceInterceptor" />
        <policyInjection/>
      </register>
    </container>
  </unity> 
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

6:运行效果:

从图中我们不难发现Aop已起到作用,在操作没有异常的情况下我们成功获得操作内容;当然其它Aop比如权限判断,事务处理等都可以用此种办法;

原文地址:https://www.cnblogs.com/wujy/p/3326316.html