• Attribute


    Attribute介绍

    咱们来说Attribute,他是一个类,所以自定义的Attribute都是继承自System.Attribute,一般命名的时候都是以Attribute结尾。在使用的时候我们可以省去Attribute,比如我们自定义一个IsEatAttribute那么在我们使用的时候就可以这样来写[IsEat],Attribute类在定义的时候,可以指定这个Attribute的应用范围,AttributeTargets枚举就列出了可以指定的范围,可以是class,也可以全部指定。就像这样:(Attribute必须写在一对方括符中)。

    [AttributeUsage(AttributeTargets.Class)]

    [AttributeUsage(AttributeTargets.All)]

     这是使用时候。

    先看一个自带的Attribute.

    Attribute 的作用

    特性Attribute 的作用是添加元数据。
    元数据可以被工具支持,比如:编译器用元数据来辅助编译,调试器用元数据来调试程序。

    Attribute是程序代码的一部分,不但不会被编译器丢弃,而且还会被编译器编译进程序集(Assembly)的元数据(Metadata)里,在程序运行的时候,你随时可以从元数据里提取出这些附加信息来决策程序的运行。

    ---------------------------------------------------------------

    自定义一个Attribute

    现在我们就来自定义一个Attribute。我们目的是要分为:好人和坏人。好人我们给饭吃,坏人我们不给饭吃。添加一个类,定义如下:

    namespace _Attribute
    {
        [AttributeUsage(AttributeTargets.Class)]
        public class IsEatAttribute:Attribute
        {
            public enum Appoint  //我首先定义一个枚举类型的指定。Appoint指定
            {
                good,
                bad
            };
            public Appoint _Appoint { get; set; }   //封装了起来,在用的时候使用形参进行赋值
            //public int id(get;set;)
            public IsEatAttribute(Appoint appoint)
            {
                _Appoint = appoint;
            }
        }
    }

    IsEatAttribute继承了Attribute.我们定义了一个枚举类型的Appoint分为好和坏。在这个类里面我们声明了一个枚举类型的_Appoint变量。并给它封装起来。你可以看到类名和下面那个方法名相同,可以看出它是一个构造函数。我们给它一个形参列表,用于给_Appoint赋值。

    定义接口:

    namespace _Attribute
    {
        public interface IMan
        {
            string Show();
        }
    }

    使用Attribute

    我们自定义了一个Attribute,下面我们来使用它。
    GoodMan.cs

    namespace _Attribute
    {
        [IsEat(IsEatAttribute.Appoint.good)]
        public class GoodMan:IMan
        {
            public string Show()
            {
               return "这是一个好人,好人可以吃饭";
            }
        }
    }

    我们在类上面Appoint(指明)了good。

    BadMan.cs

    namespace _Attribute
    {
        [IsEat(IsEatAttribute.Appoint.bad)]
        public class BadMan:IMan
        {
            public string Show()
            {
               return "这是一个坏人,坏人不给饭吃";
            }
        }
    }

    我们在类上面Appoint(指明)了bad。

    Attribute过滤

     接下来我们还是要添加一个类,Filter.

    namespace _Attribute
    {
        public class Filter
        {
            public static void Leach(IMan man)
            {
                System.Reflection.MemberInfo info = man.GetType(); //通过反射得到man的信息
                //MethodInfo获取有关成员属性的信息,并提供对成员元数据的访问
                IsEatAttribute attribute = (IsEatAttribute)Attribute.GetCustomAttribute(info, typeof(IsEatAttribute));
                                //获取当前类的标签,然后用标签与传进来的info进行比较,确认man类型.
                //得到施加在man上定制的Attribute
                if (attribute._Appoint == IsEatAttribute.Appoint.good)
                    Console.WriteLine(man.GetType().ToString() + ":" + man.Show());
                else
                    Console.WriteLine(man.GetType().ToString() + ":" + "这是坏人");
            }
        }
    }

    static Attribute GetCustomAttribute():这个方法有8种重载的版本,它被用来取出施加在类成员上指定类型的Attribute。(这是我最难理解的地方)

    来说一下为什么要用一个Filter来声明一个Leach过滤方法呢?因为,如果我们不通过过滤就去实例化对象,并且调用类里面的方法的话,就不会达到我们预期的效果。

    看一次测试结果:

    如果我们把GoodMan类上的Attribute指定成bad类,那么会出现如下结果:

    [IsEat(IsEatAttribute.Appoint.bad)]
    public class GoodMan:IMan

    总结:

    Property一般是指一对get,set方法,可以称为是类的成员属性,它大部分时候用来对类的成员变量进行读取或赋值。

    Attributes的解释如下:
    公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为。
    说的通俗些Attribute是类,不过是一类比较特殊的类,Attribute必须写在一对方括号中,用来处理.net中多种问题:序列化、程序的安全特征等等.

    扩展

    Attribute
    除了.NET提供的那些Attribute派生类之外,我们可以自定义我们自己的Attribute,所有自定义的Attribute必须从Attribute类派生。现在我们来看一下Attribute 类的细节:

    protected Attribute(): 保护的构造器,只能被Attribute的派生类调用。

    三个静态方法:

    static Attribute GetCustomAttribute():这个方法有8种重载的版本,它被用来取出施加在类成员上指定类型的Attribute

    static Attribute[] GetCustomAttributes(): 这个方法有16种重载版本,用来取出施加在类成员上指定类型的Attribute数组。

    static bool IsDefined():由八种重载版本,看是否指定类型的定制attribute被施加到类的成员上面。

    实例方法:

    bool IsDefaultAttribute(): 如果Attribute的值是默认的值,那么返回true。

    bool Match():表明这个Attribute实例是否等于一个指定的对象。

    公共属性: TypeId: 得到一个唯一的标识,这个标识被用来区分同一个Attribute的不同实例。

    我们简单地介绍了Attribute类的方法和属性,还有一些是从object继承来的。这里就不列出来了。

    下面介绍如何自定义一个Attribute: 自定义一个Attribute并不需要特别的知识,其实就和编写一个类差不多。自定义的Attribute必须直接或者间接地从Attribute这个类派生,如:

    public MyCustomAttribute : Attribute { ... }

    这里需要指出的是Attribute的命名规范,也就是你的Attribute的类名+"Attribute",当你的Attribute施加到一个程序的元素上的时候,编译器先查找你的Attribute的定义,如果没有找到,那么它就会查找“Attribute名称"+Attribute的定义。如果都没有找到,那么编译器就报错。

    对于一个自定义的Attribute,你可以通过AttributeUsage的Attribute来限定你的Attribute所施加的元素的类型。代码形式如下: [AttriubteUsage(参数设置)] public 自定义AttributeAttribute { ... }

    非常有意思的是,AttributeUsage本身也是一个Attribute,这是专门施加在Attribute类的Attribute. AttributeUsage自然也是从Attribute派生,它有一个带参数的构造器,这个参数是AttributeTargets的枚举类型。

  • 相关阅读:
    Delphi TListView刷新闪烁问题
    GO语言下载、安装、配置
    理解领域模型Domain Model
    Competing Consumers Pattern (竞争消费者模式)
    Compensating Transaction Pattern(事务修正模式)
    一致性hash算法简介
    CQRS, Task Based UIs, Event Sourcing agh!
    Circuit Breaker Pattern(断路器模式)
    Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications 云设计模式:云应用的规范架构指导
    Cache-Aside Pattern(缓存模式)
  • 原文地址:https://www.cnblogs.com/yumaster/p/5348648.html
Copyright © 2020-2023  润新知