我是靠谱客的博主 秀丽歌曲,最近开发中收集的这篇文章主要介绍C#中的 Attribute 与 Python/TypeScript 中的装饰器是同个东西吗,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

???? 优质资源分享 ????

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

前言

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

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

[HttpGet]
public Response Get() {
    return ...
}

我第一反应觉得不是,这玩意在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

使用的时候

@outer
def test():
    print('test')

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

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

outer(test)

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; }
}

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

[DemoAttribute("class")]
public class DemoClass {
    [Demo("method")]
    public void Method1() {
    }
}

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

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

因为特性只是单纯的装饰

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

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

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

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

var info = typeof(DemoClass);
var attributes = info.GetCustomAttributes(true);

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

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);
}

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

小结

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

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

参考资料

  • C#的Attribute和Typescript的装饰器之比较:https://blog.csdn.net/weixin_43263355/article/details/110137016

  • C#中如何实现类似Python中的装饰器:https://www.zhihu.com/question/36211661

  • AOP面向切面编程:https://bbs.huaweicloud.com/blogs/289045

    • 前言
  • 关于AOP

  • 具体的区别

  • Python的装饰器

  • C#的“特性”

  • 小结

  • 参考资料

    __EOF__

     - **本文作者:** [程序设计实验室](https://blog.csdn.net/biggbang)
    
  • 本文链接: https://blog.csdn.net/deali/p/16413139.html
  • 关于博主: 公众号:程序设计实验室,欢迎交流~
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角**【[推荐](javascript:void(0)????】**一下。

最后

以上就是秀丽歌曲为你收集整理的C#中的 Attribute 与 Python/TypeScript 中的装饰器是同个东西吗的全部内容,希望文章能够帮你解决C#中的 Attribute 与 Python/TypeScript 中的装饰器是同个东西吗所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部