C#/.NET Unity静态实现AOP功能——实际案例Demo代码

【C#高级语法特性锦集】

https://blog.csdn.net/qq_34202873/article/details/91043366


C# Unity依赖注入利用Attribute实现AOP功能

在做项目时,常常要对某个功能进行扩展,我们一般都是利用OOP的思想, 在原有的功能上进行扩展。

如果能用AOP思想去扩展,会使代码的整体框架更加稳定,我推荐Unity框架,接下来介绍一下如何使用。

1. 首先通过NuGet添加相关依赖

需要Unity和Unity.Interception

!!重要!!注意!!版本不要选太新版,Unity选5.6.0以前的,Interception也选5.2.0左右的即可,新版使用该案例会出现一些问题,如有解决方法请在评论指出

在这里插入图片描述

2. 添加namespace

using Unity;
using Unity.Interception.ContainerIntegration;
using Unity.Interception.Interceptors.InstanceInterceptors.InterfaceInterception;
using Unity.Interception.PolicyInjection.Pipeline;
using Unity.Interception.PolicyInjection.Policies;

3. 开始使用EntLib\PIAB Unity 实现动态代理

3.1 先写好相关特性Attribute,必须继承自HandlerAttribute

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

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

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

public class AfterLogHandlerAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new AfterLogHandler() { Order = this.Order };
    }
}
#endregion 特性

3.2 再写特性对应的行为

注[1]Order:是特性运行的顺序,具体看后面的操作实例

注[2]getNext:运行下一个函数先,如果getNext在前面,那么就是主程序运行完再运行这个特性行为(需要注意Order顺序会反过来),否则就是在特性前(Order顺序正常排序)

注[3]input:输入的参数,input[0]是第一个参数…以此类推

#region 特性对应的行为
public class UserHandler : ICallHandler
{
    public int Order { get; set; }
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        User user = input.Inputs[0] as User;
        if (user.Password.Length < 10)
        {
            return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10位"));
        }
        Console.WriteLine("参数检测无误");


        IMethodReturn methodReturn = getNext()(input, getNext); //getNext.Invoke().Invoke(input, getNext);

        //Console.WriteLine("已完成操作");

        return methodReturn;
    }
}

public class LogHandler : ICallHandler
{
    public int Order { get; set; }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="input">方法调用的参数列表</param>
    /// <param name="getNext"></param>
    /// <returns></returns>
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        User user = input.Inputs[0] as User;
        string message = $"RegUser:Username:{user.Name},Password:{user.Password}";
        Console.WriteLine("日志已记录,Message:{0},Ctime:{1}", message, DateTime.Now);
        return getNext()(input, getNext);
    }
}


public class ExceptionHandler : 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($"异常:{methodReturn.Exception.Message}");
        }
        return methodReturn;
    }
}

public class AfterLogHandler : ICallHandler
{
    public int Order { get; set; }
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        IMethodReturn methodReturn = getNext()(input, getNext);
        User user = input.Inputs[0] as User;
        string message = string.Format("RegUser:Username:{0},Password:{1}", user.Name, user.Password);
        Console.WriteLine("完成日志,Message:{0},Ctime:{1},计算结果{2}", message, DateTime.Now, methodReturn.ReturnValue);
        return methodReturn;
    }
}
#endregion 特性对应的行为

3.3 最后写相关的业务(函数方法/功能)

注[1]Order:这里特性的运行顺序是按照Order从小到大排的

注[2]DIP原则:这里最好使用依赖倒置原则来写,操作抽象会使代码更加稳定

#region 业务
[UserHandlerAttribute(Order = 1)]        
[LogHandlerAttribute(Order = 2)]
[ExceptionHandlerAttribute(Order = 3)]
[AfterLogHandlerAttribute(Order = 4)]
public interface IUserProcessor
{
    void RegUser(User user);
    User GetUser(User user);
}

public class UserProcessor : IUserProcessor
{
    public void RegUser(User user)
    {
        Console.WriteLine("用户已注册。");
        //throw new Exception("11");
    }

    public User GetUser(User user)
    {
        return user;
    }
}
#endregion 业务

4. 具体操作实现

注[1]断点:在下面注释需要打断点的那里打断点查看具体运行顺序,以便理解

public static void Show()
{
    User user = new User()
    {
        Name = "Eleven",
        Password = "12345678957576"
    };
    {
        UserProcessor processor = new UserProcessor();
        processor.RegUser(user);

        Console.WriteLine("*********************");
    }
    {

        IUnityContainer container = new UnityContainer();//声明一个容器
        container.RegisterType<IUserProcessor, UserProcessor>();//声明UnityContainer并注册IUserProcessor
        IUserProcessor processor = container.Resolve<IUserProcessor>();
        processor.RegUser(user);//没有AOP的,可在此打个断点F11进入

	//配置AOP,固定套路
        container.AddNewExtension<Interception>()
			.Configure<Interception>()
            .SetInterceptorFor<IUserProcessor>(new InterfaceInterceptor());

        IUserProcessor userprocessor = container.Resolve<IUserProcessor>();//重新实例化

        Console.WriteLine("********************");
        userprocessor.RegUser(user);//有AOP的,可在此打个断点F11进入
        userprocessor.GetUser(user);//有AOP的,可在此打个断点F11进入
    }
}

5. 小结

在这里的Unity实现,主要是用Unity内部的特性去实现AOP,本文介绍的实现方法是静态的,如果需要动态的还需写配置文件。过几天再写一篇Unity实现IOC及AOP的动态配置。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老陈聊架构

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值