.NET(C#) 面向切面编程(AOP) Autofac

AOP(Aspect Oriented Programming)是面向切面编程,用来在不修改代码的情况下,动态的添加功能,通过预编译方式和运行期动态代理实现程序功能的中统一处理业务逻辑的一种技术,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。比较常见的场景是:日志记录,错误捕获、性能监控等。本文主介绍Autofac实现AOP方法,以及相关的示例代码。

1、Autofac

Autofac与C#语言的结合非常紧密,C#里的很多编程方式都可以为Autofac使用,如可以用Lambda表达式注册组件并学习它非常的简单,性能速度也比较快简洁高效,也是.NET领域最为流行的IoC框架之一。适用于 .NET Core、ASP.NET Core、.NET 4.5.1+、通用 Windows 应用等。微软的Orchad开源程序使用的就是Autofac,从该源码可以看出它的方便和强大。

2、安装引用Autofac和Autofac.Extras.DynamicProxy

1)使用Nuget管理控制台

可以通过打开包管理器控制台(PM)并键入以下语句来安装Autofac:

Install-Package Autofac
Install-Package Autofac.Extras.DynamicProxy

2)使用Nuget图形管理器

使用Nuget的界面的管理器搜索 "Autofac" 和 "Autofac.Extras.DynamicProxy" => 找到分别点击"安装"。

3)使用.NET CLI命令安装

> dotnet add TodoApi.csproj  Autofac
> dotnet add TodoApi.csproj package Autofac.Extras.DynamicProxy

相关文档VS(Visual Studio)中Nuget的使用

3、使用静态代理实现AOP

使用面向对象的方式实现AOP,代码如下,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
    //一般每个接口或类都写在单独的.cs文件中
    //本示例为了执行查看方便才写在一起
    public class User
    {
        public string UserName { get; set; }
        public string PassWord { get; set; }
    }
    public interface IUserProcessor
    {
        void RegUser(User user);
    }
    public class UserProcessor : IUserProcessor
    {
        public void RegUser(User user)
        {
            Console.WriteLine(" 用户已注册。Name:{0},PassWord:{1} ", user.UserName, user.PassWord);
        }
    }
    //通过定义一个装饰器类实现
    public class UserProcessorDecorator : IUserProcessor
    {
        public IUserProcessor UserProcessor { get; set; }
        public UserProcessorDecorator(IUserProcessor userprocessor)
        {
            UserProcessor = userprocessor;
        }
        public void RegUser(User user)
        {
            PreProceed(user);
            UserProcessor.RegUser(user);
            PostProceed(user);
        }
        public void PreProceed(User user)
        {
            Console.WriteLine(" 方法执行前 ");
        }
        public void PostProceed(User user)
        {
            Console.WriteLine(" 方法执行后 ");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User() { UserName = "cjavapy", PassWord = "123456" };
            IUserProcessor userprocessor = new UserProcessorDecorator(new UserProcessor());
            userprocessor.RegUser(user);
            Console.ReadKey();
        }
    }
}

4、使用Autofac实现AOP

使用Autofac实现对象的动态代理,实现如下:

1)类代理拦截

using Autofac;
using Autofac.Extras.DynamicProxy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
    //一般每个接口或类都写在单独的.cs文件中
    //本示例为了执行查看方便才写在一起
    public class User
    {
        public string UserName { get; set; }
        public string PassWord { get; set; }
    }
    public interface IUserProcessor
    {
        void RegUser(User user);
    }
    /// 
    /// 拦截器 需要实现 IInterceptor接口 Intercept方法
    /// 
    class ProcessorInterception : IInterceptor
    {
        public void PreProceed(User user)
        {
            Console.WriteLine(" 方法执行前:" + user.UserName);
        }
        public void PostProceed(User user)
        {
            Console.WriteLine(" 方法执行后:" + user.UserName);
        }
        public void Intercept(IInvocation invocation)
        {
            if (invocation.Arguments.Length > 0)
            {
                PreProceed(invocation.Arguments[0] as User);
            }
            invocation.Proceed();
            if (invocation.Arguments.Length > 0)
            {
                PostProceed(invocation.Arguments[0] as User);
            }
        }
    }
    [Intercept(typeof(ProcessorInterception))]
    public class UserProcessor : IUserProcessor
    {
        /// 
        /// 必须是虚方法
        /// 
        /// 
        public virtual void RegUser(User user)
        {
            Console.WriteLine(" 用户已注册。Name:{0},PassWord:{1} ", user.UserName, user.PassWord);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User() { UserName = "cjavapy", PassWord = "123456" };
            var builder = new ContainerBuilder();
            // 启用类代理拦截
            builder.RegisterType().EnableClassInterceptors();
            //启用接口代理拦截
            //builder.RegisterType().As().InterceptedBy(typeof(ProcessorInterception)).EnableInterfaceInterceptors();
            // 命名注入
            // builder.Register(c => new ProcessorInterception())
            //        .Named("processor");
            // 类型注入
            //builder.Register(c => new UserProcessor());
            builder.Register(c => new ProcessorInterception());
            ///启用拦截器主要有两个方法:EnableInterfaceInterceptors(),EnableClassInterceptors()。
            ///EnableInterfaceInterceptors方法会动态创建一个接口代理
            //EnableClassInterceptors方法会创建一个目标类的子类代理类,需要注意的是只会拦截虚方法,重写方法
            // 获取一个带有截取管道的代理对象 
            var container = builder.Build();
            var p = container.Resolve();
            p.RegUser(user);
            Console.ReadKey();
        }
    }
}

2)接口代理拦截

using Autofac;
using Autofac.Extras.DynamicProxy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication
{
    //一般每个接口或类都写在单独的.cs文件中
    //本示例为了执行查看方便才写在一起
    public class User
    {
        public string UserName { get; set; }
        public string PassWord { get; set; }
    }
    public interface IUserProcessor
    {
        void RegUser(User user);
    }
    /// 
    /// 拦截器 需要实现 IInterceptor接口 Intercept方法
    /// 
    class ProcessorInterception : IInterceptor
    {
        public void PreProceed(User user)
        {
            Console.WriteLine(" 方法执行前:" + user.UserName);
        }
        public void PostProceed(User user)
        {
            Console.WriteLine(" 方法执行后:" + user.UserName);
        }
        public void Intercept(IInvocation invocation)
        {
            if (invocation.Arguments.Length > 0)
            {
                PreProceed(invocation.Arguments[0] as User);
            }
            invocation.Proceed();
            if (invocation.Arguments.Length > 0)
            {
                PostProceed(invocation.Arguments[0] as User);
            }
        }
    }
    //[Intercept(typeof(ProcessorInterception))]
    public class UserProcessor : IUserProcessor
    {
        public void RegUser(User user)
        {
            Console.WriteLine(" 用户已注册。Name:{0},PassWord:{1} ", user.UserName, user.PassWord);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User() { UserName = "cjavapy", PassWord = "123456" };
            var builder = new ContainerBuilder();
            // 启用类代理拦截
            //builder.RegisterType().EnableClassInterceptors();
            //启用接口代理拦截,除了上面的标签,还可以使用InterceptedBy(typeof(ProcessorInterception))的方法
            builder.RegisterType().As().InterceptedBy(typeof(ProcessorInterception)).EnableInterfaceInterceptors();
            // 命名注入
            // builder.Register(c => new ProcessorInterception())
            //        .Named("processor");
            // 类型注入
            //builder.Register(c => new UserProcessor());
            builder.Register(c => new ProcessorInterception());
            ///启用拦截器主要有两个方法:EnableInterfaceInterceptors(),EnableClassInterceptors()。
            ///EnableInterfaceInterceptors方法会动态创建一个接口代理
            //EnableClassInterceptors方法会创建一个目标类的子类代理类,需要注意的是只会拦截虚方法,重写方法
            // 获取一个带有截取管道的代理对象 
            var container = builder.Build();
            var p = container.Resolve();
            p.RegUser(user);
            Console.ReadKey();
        }
    }
}
推荐阅读
cjavapy编程之路首页