zoukankan      html  css  js  c++  java
  • C# Unity依赖注入利用Attribute实现AOP功能

    使用场景?

    很多时候, 我们定义一个功能, 当我们要对这个功能进行扩展的时候, 按照常规的思路, 我们一般都是利用OOP的思想, 在原有的功能上进行扩展。

    那么有没有一种东西, 可以实现当我们需要扩展这个功能的时候, 在不修改原来的功能代码的情况下实现, 这就是下面要说的到Unity。

    1.准备工作

    为项目添加NuGet包, 搜索Unity并且安装。

    在使用的项目中添加Unity的相关引用

    using Microsoft.Practices.Unity.InterceptionExtension;
    using Microsoft.Practices.Unity;

    2.假设场景

    刚才上面说道, Unity可实现在不修改原功能的情况下, 添加额外的扩展功能。在我们的实际开发中, 也可以举个简单的例子。

    当我们去做一个用户注册的功能, 最初的版本是完成了基本的注册功能, 后来我们需要扩展了, 给他加上注册校验, 日志处理, 和异常捕捉的几个功能, 那么接下来就演示, 如何用Unity给功能扩展。

    3.如何使用

    首先, 我们定义好一个最原始的注册功能

            public static void Show()
            {
                User user = new User()
                {
                    Name = "Eleven",
                    Password = "123123123123"
                };
    IUserProcessor porcessor = new UserProcessor();
                porcessor.RegUser(user); //简单的用户注册
    }
            public interface IUserProcessor
            {
                void RegUser(User user);
            }
    
            public class UserProcessor : IUserProcessor//MarshalByRefObject,
            {
                public void RegUser(User user)
                {
                    Console.WriteLine("注册");
                }
            }

     接下来, 我们要对这个注册进行扩展了, 添加注册校验, 日志处理, 和异常捕捉的几个功能。

    1.先定义3个特性与对应的特性行为实现, 分别是注册, 日志, 和异常。

           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 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.Invoke().Invoke(input, getNext);
                    
                    return methodReturn;
                }
            }
    
            public class LogHandler : ICallHandler    //日志处理的行为
            {
                public int Order { get; set; }
                public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate 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}", 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("异常:{0}", methodReturn.Exception.Message);
                    }
                    return methodReturn;
                }
            }

    按照现在思路, 我们要把这上面写好的几个功能添加在原来的注册功能上, 首先, 我们回到最开始定义接口的地方, 给接口添加我们定义按的3个特性

            [UserHandlerAttribute(Order = 1)] //注册校验
            [LogHandlerAttribute(Order = 2)]  //日志处理
            [ExceptionHandlerAttribute(Order = 3)] //遗产处理
            public interface IUserProcessor
            {
                void RegUser(User user);
            }

    //PS: 在上面的特性声明中, 每个对应的Order 这个属于排序, 相对于一个行为的执行顺序, 这个内部是Unity的一个实现, 所以我们使用的过程中只需要声明好标量即可。

    然后, 我们在定义好的注册方法中, 首先声明一个Unity容器UnityContainer , 然后注册其上面的接口 IUserProcessor, 最后调用其接口的注册方法。

                //声明一个容器
                IUnityContainer container = new UnityContainer();
    
                //声明UnityContainer并注册IUserProcessor
                container.RegisterType<IUserProcessor, UserProcessor>();
    
                container.AddNewExtension<Interception>().Configure<Interception>()
                    .SetInterceptorFor<IUserProcessor>(new InterfaceInterceptor());
                IUserProcessor userprocessor = container.Resolve<IUserProcessor>();
                userprocessor.RegUser(user); //调用注册方法。

    最后, 我们看一下实际效果, 很轻松的实现了用于注册时候扩展其他更多的行为

    小结:

    不难发现, Unity的实现 主要以在接口上定义的特性与实现行为  与其内部Unity容器的结合  实现的AOP功能。

    因为上面是属于静态的写法, 便于学习, 真正的实现AOP可动态配置, 在IOC里会有详细的介绍。

  • 相关阅读:
    Redis基础-基本数据类型
    C#特性
    C#反射
    Json序列化
    动态添加文本框并获取文本框的值
    iframe中镶嵌html页,并获取html页中的方法
    获取url中的参数
    发送邮件
    数据导入Excel表格
    处理xml模块、configparser模块、hashlib模块、subprocess模块
  • 原文地址:https://www.cnblogs.com/zh7791/p/7923305.html
Copyright © 2011-2022 走看看