zoukankan      html  css  js  c++  java
  • 从自定义一个特性开始,谈谈什么是特性

    C#特性:从自定义一个特性开始,谈谈什么是特性

    作为C#新手中的一员,我刚开始接触特性时,那真是一脸冏逼啊,怎么想怎么查资料都没弄明白它到底是个什么东西,有的入门教程甚至都没讲特性和反射这些概念!相信很多人第一次接触到特性就是关于系列化的知识了。

    官方概述:

    特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。 特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性。

    先弄明白一点,一个特性,如Serializable,他其实就是一个类,定义方式跟类一样,且所有特性都是直接或间接继承自Attribute基类。

    自定义一个特性

    下面就来自定义一个特性MyAttribute

        [AttributeUsage(AttributeTargets.Class,AllowMultiple=false,Inherited=false)]
        public class MyAttribute : Attribute  //类名是特性的名称
        {
            public float Version;//命名参数
            private string Name;
            public MyAttribute(string name) //name为定位参数
            {
                this.Name = name;
                this.Version = 1.0f;
            }
        }

    如何创建一个自定义特性:

    1. 一个自定义特性类必须直接或间接继承自System.Attribute特性类
    2. 为该自定义特性类指定System.AttributeUsage特性,并指定限制参数(枚举System.AttributeTargets)和可选的AllowMultiple、Inherited命名参数),AttributeUsage 的命名参数 AllowMultiple是否允许多次使用在同一目标上。Inherited命名参数表示是否同时应用于派生类型或重载版本。
    3. 类名是特性的名称。
    4. 构造函数的参数是自定义特性的定位参数(应用该特性时必须放在参数列表的最前面),也可以是无参构造函数(如[Serializable])。
    5. 任何公共的读写字段或属性都是可选的命名参数。
    6. 如果特性类包含一个属性,则该属性必须为 读写属性。
    应用特性

    下面来应用该特性:

        [My("srf", Version = 1.2f)]
        class Test11
        {
            public float n;
            public Test11()
            {
            }
            public void PrintName()
            {
            }
        }

    应用特性[My("srf", Version = 1.2f)]其实是对构造函数的调用来实例化一个特性类。
    根据约定,所有特性名称都以单词“Attribute”结束。 如可系列化标记特性Serializable,它的全称为SerializableAttribute,在代码中使用特性时,不需要指定 attribute 后缀,以上代码中同样只需要My来代表MyAttribute特性。

    关联特性

    利用反射的原理,关联特性类与目标类型(反射:主要利用Type类的属性和方法来获得一个目标类型的类型信息对象,然后根据该对象可以得到目标类型的信息,如它的字段、属性、方法名、类名等,有了这些信息,下一步就可以为所欲为了,可以还原该类型,即反系列化,甚至创建一个新类型)
    如下代码:

                //1.判断Test11类定义时,是否应用了该特性
                if (typeof(Test11).IsDefined(typeof(MyAttribute),false))
                {
                    //2.获得该特性对象,之后就可以访问它的成员(元数据)
                    MyAttribute attribute = (MyAttribute)Attribute.GetCustomAttribute(typeof(Test11), typeof(MyAttribute));
                    attribute.Version = 1.3f;
                }

    当编译器发现一个特性应用到一个目标,并发生关联时:

    1. 首先会把"Attribute"追加到特性的名称(若使用了简写),形成完整的特性类名
    2. 然后在其所有引入的命名空间中搜索该特性类,若找不到该类或它与目标不匹配,则产生编译错误
    3. 检查传递给特性的参数,并查找该特性中带定位参数的构造函数(或无参构造函数)和其它可选的命名参数(特性类的公共字段、属性),若找到匹配的构造函数,则实例化该特性类,编译器还会把目标类型的元数据传递给程序集,反射可以从程序集中读取元数据,找不到则产生编译错误。

    关联代码可以定义在目标类型内部:

        [My("srf", Version = 1.2f)]
        class Test11
        {
            public float n;
            public Test11()
            {
            }
            public void PrintName()
            {
                //1.判断是否应用了该特性
                if (this.GetType().IsDefined(typeof(MyAttribute),false))
                {
                    //2.获得该特性对象,之后就可以访问它的成员
                    MyAttribute attribute = (MyAttribute)Attribute.GetCustomAttribute(typeof(Test11), typeof(MyAttribute));
                    attribute.Version = 1.3f;
                    this.n = attribute.Version;
                }
            }
        }
    .NET预定义特性

    至于.NET预定义特性的实现原理,我没研究过,大概类似自定义特性吧,就比如系列化特性SerializableAttribute,实现原理我想大概是这样:应用[Serializable]时给目标做一个“标记”,在.NET内置程序集的某个地方判断该目标类型是否应用了该特性,然后决定是否进行系列化操作。

    总之,特性其实没那么难,它就是一个类,或者说是一个用来服务于其它类型的类,一个目标类型应用了一个特性,那么这个目标类型就可以享受该特性提供的服务了!

    以上纯属个人对特性的理解,有不对的地方请前辈们务必指正,以免误导!

     

    读完觉得学到点什么,就( 顶一个!)

     

     

     

    分类: C#
    标签: 特性反射系列化

  • 相关阅读:
    导包路径
    django导入环境变量 Please specify Django project root directory
    替换django的user模型,mysql迁移表报错 django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependen cy user.0001_initial on database 'default'.
    解决Chrome调试(debugger)
    check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values ('徐小波','XuXiaoB','男','1',' at line 1")
    MySQL命令(其三)
    MySQL操作命令(其二)
    MySQL命令(其一)
    [POJ2559]Largest Rectangle in a Histogram (栈)
    [HDU4864]Task (贪心)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6899081.html
Copyright © 2011-2022 走看看