• 仿 MVC 三大特性


    1.先做个小例子

      特性,只能通过反射实现

      我们自定义一个特性

        public class CustomAttribute : Attribute
        {
            public int Id;
            public string Name;
            public string Reamrk;
            public string Desc;
            public CustomAttribute() : this(0, "") { }//如果没传参,使用this给默认值
            public CustomAttribute(int _id, string _name)
            {
                this.Id = _id;
                this.Name = _name;
            }
            public void Show()
            {
                Console.WriteLine($"{Id}_{Name}_{Reamrk}_{Desc}");
            }
        }

      写一个类并注册特性

        [Custom(123,"kxy",Desc ="是个帅哥",Reamrk ="学员")]
        public class Student
        {
            [Custom(124, "wzz", Desc = "是个丑逼", Reamrk = "学员")]
            public void Study()
            {
                Console.WriteLine($"正在学习");
            }
        }

      实现特性调用,只能通过反射,没办法和MVC那样直接调用接口特性就会执行(因为MVC已经封装好了调用的反射机制)

        class Program
        {
            static void Main(string[] args)
            {
                Student student = new Student();
                Type type = student.GetType();
                // 判断该类是否注册了CustomAttribute
                if (type.IsDefined(typeof(CustomAttribute), true))
                {
                    var attribute = type.GetCustomAttribute<CustomAttribute>();
                    attribute.Show();
                }
    
                MethodInfo method = type.GetMethod("Study");
                // 判断该方法是否注册了CustomAttribute
                if (method.IsDefined(typeof(CustomAttribute), true))
                {
                    var attribute = method.GetCustomAttribute<CustomAttribute>();
                    attribute.Show();
                }
    
                // 执行了特性之后执行方法
                student.Study();
                Console.ReadLine();
            }
        }

      结果:

      由上可知,执行步骤先是执行类注册、在是方法注册的特性,然后再是执行我们需要的方法

      这个思路和MVC 提供的特性是一致的

    2.MVC特性思路

      先定义三大特性

    namespace Study.CustomMVCAttribute.CustomMVCAttribute
    {
        /// <summary>
        /// 基类不做操作
        /// 所有Filter只打印,不实现功能
        /// </summary>
        public class FilterAttribute : Attribute { }
        /// <summary>
        /// 权限Filter
        /// </summary>
        public class AuthorizeAttribute : FilterAttribute
        {
            public void OnAuthorization()
            {
                Console.WriteLine("OnAuthorization");
            }
        }
        /// <summary>
        /// 动作Filter
        /// </summary>
        public class ActionFilterAttribute : FilterAttribute
        {
            public void OnActionExecuting()
            {
                Console.WriteLine("OnActionExecuting");
            }
            public void OnActionExecuted()
            {
                Console.WriteLine("OnActionExecuted");
            }
            // OnResultExecuting 和 OnResultExecuted 先不管
        }
        /// <summary>
        /// 捕捉异常Filter
        /// </summary>
        public class HandleErrorAttribute : FilterAttribute
        {
            public void OnException()
            {
                Console.WriteLine("OnException");
            }
        }
    }

      定义 ControllerActionInvoker

    using System;
    using System.Linq;
    using System.Reflection;
    
    namespace Study.CustomMVCAttribute.CustomMVCAttribute
    {
        public class ControllerActionInvoker
        {
            /// <summary>
            /// 实例化
            /// </summary>
            /// <param name="instance">调用的实例</param>
            /// <param name="action">方法名</param>
            /// <param name="parameters">参数</param>
            public static void InvokeAction(object instance, string action, object[] parameters = null)
            {
                Type type = instance.GetType();
                MethodInfo method = type.GetMethod(action);
                if (method.IsDefined(typeof(FilterAttribute), true))
                {
                    var filterList = method.GetCustomAttributes<FilterAttribute>();
                    try
                    {
                        // 授权
                        AuthorizeAttribute authorize = (AuthorizeAttribute)filterList.FirstOrDefault(v => v is AuthorizeAttribute);
                        if (authorize != null)
                        {
                            authorize.OnAuthorization();
                        }
                        // 方法执行前
                        var actionList = filterList.Where(v => v is ActionFilterAttribute);
                        foreach (var item in actionList)
                        {
                            ((ActionFilterAttribute)item).OnActionExecuting();
                        }
                        // 这里执行方法
                        method.Invoke(instance, parameters);
                        // 方法执行后
                        foreach (var item in actionList)
                        {
                            ((ActionFilterAttribute)item).OnActionExecuted();
                        }
                    }
                    catch (Exception ex)
                    {
                        // 异常捕捉,包括整个动作
                        HandleErrorAttribute handleError = (HandleErrorAttribute)filterList.FirstOrDefault(v => v is HandleErrorAttribute);
                        if (handleError != null)
                        {
                            handleError.OnException();
                        }
                    }
                }
            }
        }
    }

      注册

    namespace Study.CustomMVCAttribute
    {
        public class Student
        {
            [Authorize]
            [ActionFilter]
            [HandleError]
            public void Study()
            {
                Console.WriteLine($"正在学习");
            }
        }
    }

      调用

                Student student = new Student();
                ControllerActionInvoker.InvokeAction(student, "Study");
  • 相关阅读:
    日常练习-利用python的random模块模拟身份证号码
    学习笔记-redis
    学习笔记-AJAX&JSON
    学习笔记-JQuery
    学习笔记-Filter&Listener
    学习笔记-EL&JSTL
    学习笔记-Cookie&Session
    学习笔记-Response
    学习笔记-XML
    JToken中并没有Value这个属性,但在运行时可以看到,用dyna可以取到这个属性值
  • 原文地址:https://www.cnblogs.com/wskxy/p/10900962.html
Copyright © 2020-2023  润新知