在通过Visual Studio创建的C#程序集中,都包含了一个AssemblyInfo.cs的文件,在这个文件中,我们常常会看到这样的代码

[assembly: AssemblyTitle("AttributeTutorial")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AttributeTutorial")]
[assembly: AssemblyCopyright("Copyright ©  2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

从这些代码及他们的注释中,我们大概知道他们是用来描述程序集的相关信息,那么是不是我们平常写的代码中的类、类成员是不是也有这样的附加信息呢?答案是肯定的。比如最常见的位枚举、调用另一种语言开发的dll...

    [Flags]
    enum Actions
    {
        None = 0,
        Read = 0x01,
        Write = 0x02,
        ReadWrite = Read | Write,
        Delete = 0x04
    }
  [DllImport("user32.dll")]
  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

定制自己的Attribute

定制自己的Attribute类,首先要继承System.Attribute,并用Attribute作为后缀。下面的例子中的DescriptionAttribute其实在System.ComponentModel下已近有实现,这里我们只是作为一个自己的简单的例子

    //AttributeUsage的第一个参数,告诉编译器这个特性应用的范围,第二个参数指的是派生类及重写成员是否也继承该特性,第三个参数表示是否可以为类型或成员指定多个特性
    [System.AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
    sealed class DescriptionAttribute : Attribute
    {
        // See the attribute guidelines at
        //  http://go.microsoft.com/fwlink/?LinkId=85236
        readonly string description;

        // This is a positional argument
        public DescriptionAttribute(string description)
        {
            this.description = description;

            // TODO: Implement code here
        }

        public string Description
        {
            get { return description; }
        }

        // This is a named argument
        public int NamedInt { get; set; }
    }

下面我们就用刚才自定义的特性,来简单的完成一些事情,首先我们像下面那样把刚才的枚举类型加上我们定义的特性

    [Flags]
    [Description("文件的访问")]
    enum Actions
    {
        None = 0,
        Read = 0x01,
        Write = 0x02,
        ReadWrite = Read | Write,
        Delete = 0x04
    }

那么加上这个特性有什么用呢?怎么体现他的作用呢?不要着急,我们这就来实现

    [Description("主程序")]
    class Program
    {
        static void Main(string[] args)
        {
            ClassDescriptionDisplay(typeof(Actions));
            ClassDescriptionDisplay(typeof(Program));
            Console.ReadKey();
        }

        static void ClassDescriptionDisplay(Type type)
        {
            if (type.IsDefined(typeof(DescriptionAttribute), false))//检测类型是否包含此特性
            {
                DescriptionAttribute attrs = (DescriptionAttribute)type.GetCustomAttributes(typeof(DescriptionAttribute), false)[0];//获取特性
                Console.WriteLine("{0}:{1}",type.Name,attrs.Description);
            }
            else
            {
                //另外的处理
            }
        }
    }

通过上面的代码,现在我们知道,我们可以为类及他的成员添加好配置,然后在程序运行的过程中根据配置动态的去处理一些问题。其实这个也就是特性的最大功能。

应用

特性的应用范围很广,比如我们可以为实体类的各个属性添加一个特性,这样的话在保存数据的时候不用再一个个的去写属性的判断,比如序列化的时候,只想序列化部分字段,但是要完成这些功能,还需要进一步学习反射的相关知识,这一篇我们的重点是在定制特性

    public class RegisterViewModel
    {
        [Required]
        [EmailAddress]
        [Display(Name = "电子邮件")]
        public string Email { get; set; }

        [Required]
        [StringLength(100, ErrorMessage = "{0} 必须至少包含 {2} 个字符。", MinimumLength = 6)]
        [DataType(DataType.Password)]
        [Display(Name = "密码")]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "确认密码")]
        [Compare("Password", ErrorMessage = "密码和确认密码不匹配。")]
        public string ConfirmPassword { get; set; }
    }

学会给你的类(及成员)来定制一套自己的Attribute吧的更多相关文章

  1. C++点滴----关于类常成员函数

    关于C++中,类的常成员函数 声明样式为:   返回类型 <类标识符::>函数名称(参数表) const 一些说明: 1.const是函数声明的一部分,在函数的实现部分也需要加上const ...

  2. c++函数模板作为类的成员函数,编译报错LNK2019的解决方法

    为了使某个类的成员函数能对不同的参数进行相同的处理,需要用到函数模板,即template<typename T> void Function(). 编译时报错LNK2019 解决方法: 1 ...

  3. fielderror里的fieldName代表的是jsp里的fieldName还是Action类的成员变量?(待解答)

    1.值栈的Action对象中会有一个fielderror属性,代表着字段错误. fielderror是Map<String,List<String>>类型 例如下面的值栈里可看 ...

  4. [.net 面向对象编程基础] (10) 类的成员(字段、属性、方法)

    [.net 面向对象编程基础] (10) 类的成员(字段.属性.方法) 前面定义的Person的类,里面的成员包括:字段.属性.方法.事件等,此外,前面说的嵌套类也是类的成员. a.类的成员为分:静态 ...

  5. 深入理解PHP内核(十四)类的成员变量及方法

    原文链接:http://www.orlion.ga/1237/ 类的成员变量在PHP中本质是一个变量,只是这些变量都归属于某个类,并且给这些变量是有访问控制的. 类的成员方法在PHP中本质是一个函数, ...

  6. [javaSE] 反射-获取类的成员属性和构造方法

    成员属性和构造方法皆为对象,通过Class对象的方法可以得到 package com.tsh.reflect; import java.lang.reflect.Constructor; import ...

  7. [转载]能不能同时用static和const修饰类的成员函数?

    题目(一):我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函数(写在函数的最后表示不能修改成员变量,不是指写在前面表示返回值为常量).请问:能不能同时用static和con ...

  8. 回调函数中使用MFC类的成员或对话框控件的简单方法

    在MFC的很多程序中,常常需要在回调函数中调用MFC类的类成员变量.类成员函数,亦或者对话框控件的句柄.由于回调函数是基于C编程的Windows SDK的技术,而类成员又有this指针客观条件限制.. ...

  9. Python全栈--9.1--面向对象进阶-super 类对象成员--类属性- 私有属性 查找源码类对象步骤 类特殊成员 isinstance issubclass 异常处理

    上一篇文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象 ...

随机推荐

  1. 关于Visual Studio 未能加载各种Package包的解决方案

    问题: 打开Visual Studio 的时候,总提示未能加载相应的Package包,有时候还无法打开项目,各种提示 解决方案: 进入用户目录 C:\Users\用户名\AppData\Local\M ...

  2. continue break 区别

    在循环中有两种循环方式 continue , break continue 只是跳出本次循环, 不在继续往下走, 还是开始下一次循环 break  将会跳出整个循环, 此循环将会被终止 count = ...

  3. 企业做数据缓存是使用Memcached还是选Redis?

    企业是使用Memcached还是选Redis? 在构建一款现代且由数据库驱动的Web应用程序并希望使其拥有更为出色的性能表现时,这个问题总会时不时出现.并给每一位开发人员带来困扰.在考虑对应用程序的性 ...

  4. 屌丝giser成长记-大学篇

    作为一名屌丝giser的我,刚接触gis专业是2007年的大一,好悲催,当时gis这个专业是被调剂的,我压根都不知道gis为何物,那时候gis冷门的一逼,报名这个专业的寥寥无几.记得那时候得知被调剂到 ...

  5. Web安全开发之验证码设计不当引发的撞库问题

    感谢某电商平台安全工程师feiyu跟我一起讨论这个漏洞的修复.以往在安全测试的过程中后台经常存在验证码不失效果造成的撞库问题,甚至在一些银行或者电商的登录与查存页面同样存在这个问题,一旦造成撞库无论对 ...

  6. App 审核由于 IPv6 网络问题被拒

    昨天 提交App Store 的时候被拒了 We discovered one or more bugs in your app when reviewed on iPhone running iOS ...

  7. Atitit.研发管理软件公司的软资产列表指南

    Atitit.研发管理软件公司的软资产列表指南 1. Isv模型下的软资产1 2. 实现层面implet1 3. 规范spec层1 4. 法则定律等val层的总结2 1. Isv模型下的软资产 Sof ...

  8. 第14章 Linux启动管理(3)_系统修复模式

    3. 系统修复模式 3.1 单用户模式 (1)在grub界面中选择第2项,并按"e键"进入编辑.并在"-quiet"后面加入" 1",即&q ...

  9. 学习笔记:7z在delphi的应用

    最近做个发邮件的功能,需要将日志文件通过邮件发送回来用于分析,但是日志文件可能会超级大,测算下来一天可能会有800M的大小.所以压缩是不可避免了,delphi中的默认压缩算法整了半天不太好使,就看了看 ...

  10. 机器指令翻译成 JavaScript —— No.6 深度优化

    第一篇 中我们曾提到,JavaScript 最终还得经过浏览器来解析.因此可以把一些优化工作,交给脚本引擎来完成. 现代浏览器的优化能力确实很强,但是,运行时的优化终归是有限的.如果能在事先实现,则可 ...