• C#中的 Attribute 与 Python/TypeScript 中的装饰器是同个东西吗


    🚀 优质资源分享 🚀

    学习路线指引(点击解锁)知识定位人群定位
    🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
    💛Python量化交易实战💛入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

    前言

    最近成功把「前端带师」带入C#的坑~~(实际是前端带师开始从cocos转unity游戏开发了)~~

    某天,「前端带师」看到这段代码后问了个问题:[这个是装饰器]?

    [HttpGet]
    public Response Get() {
        return ...
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我第一反应觉得不是,这玩意在C#中叫“特性”(英文名Attribute,下文统称为特性),在Java中叫注解,虽然写法和Python/TypeScript中的差不多,但印象中实现方式应该是不同的。

    但咱学理工科的就是要严谨,不能仅凭经验和感觉,为此,我查了一下资料,看了之前杨旭大佬推荐的《C# in nutshell》这本书,不仅确认了这个问题的答案,也对Attribute有了更多了解。

    关于AOP

    “特性”、装饰器,其实都是设计模式中的装饰器模式,同时也是AOP思想。

    AOP是Aspect Oriented Programming,即面向切面编程。

    AOP把系统分解为不同的关注点,或者称之为切面(Aspect),是一种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想

    比如现在有一个网站,有购物、社交、游戏等多种功能且对所有用户开放,现在需要限制只有高级会员才能使用其中的几个功能,我们可以在每个模块加上if判断,但这样侵入性太强,且会造成大量重复代码;换成AOP的方法就是使用装饰器,在需要高级会员的地方加上限制就行~

    具体的区别

    先来看看语法上的不同

    Python的装饰器

    先来看看Python中的装饰器,在Python中函数是一等公民,装饰器也是个函数,其内部又内嵌了另一个函数

    def outer(func):
        def inner():
            # ... 一些代码
            result = func()
            return result
        return inner
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用的时候

    @outer
    def test():
        print('test')
    
    
    • 1
    • 2
    • 3
    • 4

    使用时语法和Java的注解一样,以@开头

    其实这是个语法糖,实际的效果等同于

    outer(test)
    
    
    • 1
    • 2

    test函数作为参数传入给装饰器,之后这段代码的执行顺序如下:

    • def outer(func):装饰器定义
    • @outer:装饰器语法糖,直接直接执行outer函数,将test函数作为参数传入
    • outer:执行装饰器语法规则,将test函数替换成inner函数
    • inner:执行inner函数代码
    • test:根据inner中的这行代码:result = func(),执行test函数代码
    • 返回

    在Python这种动态语言中,实现装饰器模式确实是比静态语言容易的,被装饰的内容作为参数传入装饰器,装饰器可以直接访问到被装饰的内容进行一些处理。

    C#的“特性”

    C#中,“特性”是一个类,继承自Attribute类,然后可以包含任意你想要的属性字段

    AttributeUsage特性修饰,可以指定该特性可以修饰哪些代码元素

    [AttributeUsage(AttributeTargets.Class |
    AttributeTargets.Constructor |
    AttributeTargets.Field |
    AttributeTargets.Method |
    AttributeTargets.Property,
    AllowMultiple = true)]
    public class DemoAttribute : Attribute {
        public DemoAttribute(string param1) {
            this.param1 = param1;
        }
        
        public string param1 { get; set; }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    构造方法中的参数,就是使用特性时传入的参数,比如这样:

    [DemoAttribute("class")]
    public class DemoClass {
        [Demo("method")]
        public void Method1() {
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    PS:特性使用时可以省略后面的"Attribute",所以DemoAttributeDemo是同个东西

    这样写了之后并不会产生什么效果

    因为特性只是单纯的装饰

    在代码运行的时候,C#编译器先实例化DemoAttribute这个类,然后再实例化DemoClass这个类,且在DemoAttribute内是无法获取到被装饰的内容的。

    为了使装饰起效果,需要搭配使用反射~

    反射指程序可以访问、检测和修改它本身状态或行为的一种能力。

    通过下面的代码可以获取到装饰在DemoClass上的特性

    var info = typeof(DemoClass);
    var attributes = info.GetCustomAttributes(true);
    
    
    • 1
    • 2
    • 3

    通过下面的代码可以获取被装饰的方法,和装饰参数啥的

    foreach (var methodInfo in typeof(DemoClass).GetMethods()) {
        var attribute = (DemoAttribute) Attribute.GetCustomAttribute(methodInfo, typeof(DemoAttribute));
        if (attribute != null)
            Console.WriteLine("方法 {0} 被装饰,装饰参数 {1}", methodInfo.Name, attribute.param1);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    获取到这些信息后,通过反射提供的其他功能再进行一些处理,也就实现了所谓的AOP

    小结

    所以,C#的特性和Python/TypeScript中的装饰器,虽然写法用法不一样,但殊途同归,要实现的目的确实是差不多的。

    但要说是同样的东西又不严谨,所以应该同样的东西,不过都是各自语言中实现AOP的方式。

    参考资料

    • 本文链接: https://blog.csdn.net/deali/p/16413139.html
    • 关于博主: 公众号:程序设计实验室,欢迎交流~
    • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
    • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角**【[推荐](javascript:void(0)😉】**一下。
  • 相关阅读:
    CentOS如何使用Htop监控工具
    15天深度复习JavaWeb的详细笔记(八)——jsp
    Python算法练习 10.23
    第八章第二节:Java继承之protected、final关键字和组合
    python 学生编程--3 多彩同心圆
    接口的安全设计要素:ticket,签名,时间戳
    vue接口封装 路由拦截处理
    详解Volatile关键字
    神经网络用于控制的优越性,神经网络稳定性理论
    数字式传感器技术指标你知道多少
  • 原文地址:https://blog.csdn.net/qq_45562973/article/details/125468904