Ioc 之 Unity的AOP功能

  前面我们介绍了Unity的依赖注入功能,现在来介绍下Unity的AOP功能。AOP是面向切面编程,它能够使我们在不改变现有代码结构的情况下额外的为其添加一些功能。

  我们还是使用配置文件来对类型进行注入

<configuration>
  <configSections>
    <!--<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>-->
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
  </configSections>
  <unity>
    <!--<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>-->
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
    <containers>
      
      <container name="IocContainer">
        <!-- 格式:类名,程序集名称 -->
        <register type="IocDemo.IService.IPay, IocDemo.IService" mapTo="IocDemo.Service.WeChatPay, IocDemo.Service"/>
        <register type="IocDemo.IService.IOrder,IocDemo.IService" mapTo="IocDemo.Service.Order,IocDemo.Service">
          <lifetime type="transient" />
          <constructor>
            <!--<param name="id" type="System.Int32" value="3" />-->
            <!--<param name="iPay" type="IocDemo.IService.IPay,IocDemo.IService"></param>-->
          </constructor>
        </register>
        
      </container>
      
    </containers>
  </unity>
</configuration>

  接着先来看一下代码方式怎么实现AOP功能。

namespace IocDemo.Aop
{
    #region 特性对应的行为
    public class UserCallHandler : ICallHandler
    {
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            Console.WriteLine("参数检测无误");
            IMethodReturn methodReturn = getNext()(input, getNext); //getNext.Invoke().Invoke(input, getNext);
            return methodReturn;
        }
    }

    public class LogCallHandler : ICallHandler
    {
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            Console.WriteLine("日志已记录,Message:{0},CreateTime:{1}", "测试LogHandler", DateTime.Now);
            return getNext()(input, getNext);
        }
    }


    public class ExceptionCallHandler : ICallHandler
    {
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            IMethodReturn methodReturn = getNext()(input, getNext);
            if (methodReturn.Exception == null)
            {
                Console.WriteLine("无异常");
            }
            else
            {
                Console.WriteLine("异常:{0}", methodReturn.Exception.Message);
            }
            return methodReturn;
        }
    }

    public class AfterLogCallHandler : ICallHandler
    {
        public int Order { get; set; }
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            IMethodReturn methodReturn = getNext()(input, getNext);
            Console.WriteLine("完成日志,Message:{0},CreateTime:{1},计算结果{2}", "测试LogHandler", DateTime.Now, methodReturn.ReturnValue);
            return methodReturn;
        }
    }
    #endregion 特性对应的行为

    #region 特性
    public class UserHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            ICallHandler handler = new UserCallHandler() { Order = this.Order };
            return handler;
        }
    }

    public class LogHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new LogCallHandler() { Order = this.Order };
        }
    }

    public class ExceptionHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new ExceptionCallHandler() { Order = this.Order };
        }
    }

    public class AfterLogHandlerAttribute : HandlerAttribute
    {
        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new AfterLogCallHandler() { Order = this.Order };
        }
    }
    #endregion 特性
}
namespace IocDemo.IService
{
    [UserHandler(Order = 3)]
    [LogHandler(Order = 5)]
    [AfterLogHandler]
    [ExceptionHandler]
    public interface IOrder
    {
        string ToPay();
    }
}

 在代码中使用 container.AddNewExtension 加入AOP

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "Config\\Unity.Config");//找配置文件的路径
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);

IUnityContainer container = new UnityContainer();
section.Configure(container, "IocContainer");

container.AddNewExtension<Interception>().Configure<Interception>().SetInterceptorFor<IOrder>(new InterfaceInterceptor());

IOrder order = container.Resolve<IOrder>();
Console.WriteLine(order.ToPay());
Console.ReadLine();

运行结果:

  可以看到,使用代码方式实现AOP要编写的代码很多,需要编写继承 Unity.Interception.PolicyInjection.Policies.HandlerAttribute的属性,重写CreateHandler方法,该方法需要返回一个ICallHandler对象,然后需要将继承HandlerAttribute属性的attribute加在需要拦截的接口上面,调用的时候就会命中ICallHandler里面的Invoke方法。

  标记Attribute的方式有三种,一般使用第3种方式:

  1、TransparentProxyInterceptor:直接在类的方法上进行标记,但是这个类必须继承MarshalByRefObject...不建议用
  2、VirtualMethod:直接在类的方法上进行标记,但这个方法必须是虚方法(就是方法要带virtual关键字)
  3、InterfaceInterceptor:在接口的方法上进行标记,这样继承这个接口的类里实现这个接口方法的方法就能被拦截

 

  最后,让我们来看一下配置文件怎么配置AOP。

 <container name="IocContainer">
        <!-- 格式:类名,程序集名称 -->
        <register type="IocDemo.IService.IPay, IocDemo.IService" mapTo="IocDemo.Service.WeChatPay, IocDemo.Service"/>
        <register type="IocDemo.IService.IOrder,IocDemo.IService" mapTo="IocDemo.Service.Order,IocDemo.Service">
          <interceptor type="InterfaceInterceptor"/>
          <interceptionBehavior type="IocDemo.Aop.LogBehavior, IocDemo.Aop"/>
        </register>
        
      </container>

定义一个实现IInterceptionBehavior的LogBehavior类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity.Interception.InterceptionBehaviors;
using Unity.Interception.PolicyInjection.Pipeline;

namespace IocDemo.Aop
{
    public class LogBehavior : IInterceptionBehavior
    {
        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            Console.WriteLine("LogBehavior before");
            IMethodReturn method = getNext()(input, getNext);
            Console.WriteLine("LogBehavior after");
            return method;
        }

        public bool WillExecute
        {
            get { return true; }
        }
    }
}

代码中调用

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "Config\\unity.config");//找配置文件的路径
                Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);

                IUnityContainer container = new UnityContainer();
                section.Configure(container, "IocContainer");
                

                //被拦截
                /*
                    实现Unity.Interception.InterceptionBehaviors.IInterceptionBehavior接口,进入Invoke方法
                 */
                IOrder order = container.Resolve<IOrder>();
                Console.WriteLine(order.ToPay());
                Console.ReadLine();

运行结果可以看到,在调用ToPay之前进入了LogBehavior的Invoke方法

  可见使用配置文件的方式实现AOP比代码方式实现简单很多。需要注意的是,再引用Unity的时候需要注意Unity和Unity.Interception版本的问题,笔者在这个版本问题上调试了很久才找到匹配的版本。

转载于:https://www.cnblogs.com/jesen1315/p/11043937.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值