1.Attribute的定义与作用:

公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。Attributes和Microsoft .NET Framework文件的元数据保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为.比如在WCF中常用的序列化。比如添加的[DataMenber]就是一种标签。以及xml序列化也是一样的。

2.Reflect的定义与作用

反射可以用于观察并修改程序在运行时的执行。一个reflection-oriented程序组件可以监测一个范围内的代码执行情况,可以根据期望的目标与此相关的范围修改本身。这通常是通过在运行时动态分配程序代码实现。在面向对象的编程语言如Java中,反射允许在编译期间不知道接口的名称,字段、方法的情况下在运行时检查类、接口、字段和方法。它还允许的实例化新对象和调用的方法。(摘抄至维基百科). 其实可以简单理解为,通过反射可以很轻易的获取到一个类中的所有方法属性字段状态。

3.为了更方便的认识反射以及Attribute的应用,下面有个例子.

业务背景如下: 有个Person对象,目前只有Name和Num属性,然后要用方法校验Person对象的合法性。

判断规则:  1.Name必填,若Name为空,则提示"Name不能为空";

2.Num可以为空,但是若有数据的话必须由数字组成,若为非数字字符串则弹出"格式不正确".

          3.Address可以为空,若有数据的话长度不能超过12,若超过12则提示"Address 长度不能超过12"

需要考虑: 对于Person类,以后熟悉的判断规则可能会变化,也可能增加属性,减少属性。

  4.解决方案一:

对于常规解决方案,可能大家会想到。目前只有Name,Address,Num三个属性,每次我就写三个代码段分别对Name,Address,Num验证。如果增加属性, 比如增加了公共属性EmailAddress,那么就必须添加验证字符串是否是邮箱的代码,若删除了某个属性,就吧判断该属性是否合格的代码删除掉不进行判断。这个也是我最开始想到的方法。不过这样不好的地方是可维护性不好。改动太大了。而且会导致重复代码。不如如果需求改成Address不能为空了。那么在判断address是否合法的时候还要去添加判断不能为空的情况。

5.解决方案二:

为了解决方案一的问题,其实我们可以通过Attribute和反射来实现。思路如下:

5.1 首先我们创建一个PersonCheckAttribute对象,他继承与System.Attribute.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ReflectTest.Model
{
public class PersonCheckAttribute:Attribute
{ // 三个bool变量用于确定是有要验证这些信息
private bool checkEmpty = false; //是否为空
private bool checkMaxLength = false; //最大长度
private bool checkRegex = false; //用正则表达式验证参数(是邮箱,是否刷数字) private int maxLength = ;
private string regexStr = string.Empty; public bool CheckEmpty
{
get { return this.checkEmpty; }
set { this.checkEmpty = value; }
} public bool CheckMaxLength
{
get { return this.checkMaxLength; }
set { this.checkMaxLength = value; }
} public bool CheckRegex
{
get { return this.checkRegex; }
set { this.checkRegex = value; }
} public int MaxLength
{
get { return this.maxLength; }
set { this.maxLength = value; }
} public string RegexStr
{
get { return this.regexStr; }
set { this.regexStr = value; }
}
}
}

5.2 然后我们来添加Person类。注意里面的标签。

Tips:我在里面打了标签,对于5.1的PersonCheckAttribute类中bool变量用来确定是否要进行验证,公共属性用来存取判断参数。
  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ReflectTest.Model
{
public class Person
{
[PersonCheck(CheckEmpty=true)]
public string Name { get; set; } [PersonCheck(CheckRegex = true, RegexStr = "^[0-9]*[1-9][0-9]*$")]
public string Num { get; set; } [PersonCheck(CheckMaxLength = true, MaxLength = )]
public string Address { get; set; }
}
}

5.3 属性已经搞定,下面来看看,如何通过反射来获取类的公共属性,以及每个属性的Attribute。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ReflectTest.Model;
using System.Reflection;
using System.Text.RegularExpressions; namespace ReflectTest.Business
{
public class PersonCheck
{
// 获取所有的错误提示
public static string GetErrorMessage(Person person)
{
PropertyInfo[] propertyInfos = person.GetType().GetProperties(); // 获取一个类的所有属性
string errorMsg = string.Empty; //对所有公用属性(Name,Num,Address)遍历
foreach (PropertyInfo info in propertyInfos)
{
errorMsg += GetSignalPropertity(info, person);
}
return errorMsg;
} // 获取单个公共属性的Attribute.也就是model类里面的[PersonCheck]信息
private static string GetSignalPropertity(PropertyInfo propertyInfo,Person person)
{
// 因为对于此示例,每个Properties(属性)只有一个Attribute(标签),所以用了first()来获取,
// 不过有一点,就是必须在属性里面添加[PersonCheck]标签,但是可以不设置表情里面的字段.因为没有的.GetCustomAttributes()返回为null.指向first会报错.
// PersonCheckAttribute attribute = propertyInfo.GetCustomAttributes().First() as PersonCheckAttribute; string errorMsg = string.Empty; //以下的if语句是判断标签里面的设置,设置了什么就执行什么数据校验
PersonCheckAttribute attribute = propertyInfo.GetCustomAttribute(typeof(PersonCheckAttribute)) as PersonCheckAttribute;
if (attribute != null)
{
if (attribute.CheckEmpty)
{
string obj = propertyInfo.GetValue(person) as string;
if (string.IsNullOrEmpty(obj))
{
errorMsg += Environment.NewLine + string.Format("{0} 不能为空", propertyInfo.Name);
}
} if (attribute.CheckMaxLength)
{
string obj = propertyInfo.GetValue(person) as string;
if (obj != null && obj.Length > attribute.MaxLength)
{
errorMsg += Environment.NewLine + string.Format("{0} 不能超过最大程度{1}", propertyInfo.Name, attribute.MaxLength);
}
} // 对于判断数字邮箱都可以通过正则表达式
if (attribute.CheckRegex)
{
string obj = propertyInfo.GetValue(person) as string;
Regex regex = new Regex(attribute.RegexStr);
if (obj != null && !regex.IsMatch(obj))
{
errorMsg += Environment.NewLine + string.Format("{0} 格式不对", propertyInfo.Name);
}
}
}
return errorMsg;
}
}
}

5.4 下面来看运行结果。

5.4.1 若Person p = new Person(){Num=“abc”};调用GetErrorMessage(Person person)方法后运行结果如下。Person不能为空.
    

5.4.2 若Person p = new Person(){Num=“123”,Address=“chengdu,Tianfu SoftwarePark”};调用GetErrorMessage(Person person)方法后运行结果如下。Person不能为空.

  

  6.分析反射的好处:

如果需求修改,Address不能为空了,我只需要在Address的标签里面设置CheckEmpty=true,而不需要重新修改逻辑代码。同理,如果要给Person类添加属性EmailAddress,那么只需要在Person类里面添加属性EmailAddress设置标签为【PersonCheck(CheckRegexStr = true,regexStr="*")】,*未判断是否是合法有效的正则表达式即可。

  7.总结:

其实小弟也是刚接触反射。有很多东西也是一知半解。目前对反射的认识也就这么多,有其他大牛应用更多这方面的,如果有什么好的想法和资料也请大家分享一下,相互学习,相互提升。代码链接:https://github.com/FourLeafClover/AttributeAndReflect

  

C#基础---Attribute(标签) 和 reflect(反射) 应用的更多相关文章

  1. C#基础---Attribute(标签) 和 reflect(反射) 应用二

    以前我有写过一篇有关,打标签和反射的应用,主要用于类中字段的验证.下面是连接 C#基础---Attribute(标签) 和 reflect(反射) 应用. 这个项目迭代发现公司项目里面发现老代码对业务 ...

  2. Java 基础之详解 Java 反射机制

    一.什么是 Java 的反射机制?   反射(Reflection)是Java的高级特性之一,是框架实现的基础,定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: ...

  3. [转] Git 基础 - 打标签

    2.6 Git 基础 - 打标签 打标签 同大多数 VCS 一样,Git 也可以对某一时间点上的版本打上标签.人们在发布某个软件版本(比如 v1.0 等等)的时候,经常这么做.本节我们一起来学习如何列 ...

  4. h5标签基础 meta标签

    <meta>标签位于<head>标签里面,具体作用有如下: 1.设置网页编码 eg: <meta charset="utf-8"/>  ,//u ...

  5. js基础--浏览器标签页隐藏或显示状态 visibility详解

    欢迎访问我的个人博客:http://www.xiaolongwu.cn 前言 在工作中我们可能会遇到这样的需求,当浏览器切换到别的标签页或着最小化时,我们需要暂停页面上正在播放的视频或者音乐,这个需求 ...

  6. JAVA 构造器, extends[继承], implements[实现], Interface[接口], reflect[反射], clone[克隆], final, static, abstrac

    记录一下: 构造器[构造函数]: 在java中如果用户编写类的时候没有提供构造函数,那么编译器会自动提供一个默认构造函数.它会把所有的实例字段设置为默认值:所有的数字变量初始化为0;所有的布尔变量设置 ...

  7. HTML&CSS基础-html标签的实体

    HTML&CSS基础-html标签的实体 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HTML源代码 <!DOCTYPE html> <html&g ...

  8. HTML&CSS基础-meta标签

    HTML&CSS基础-meta标签 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.常见字符集 1>ASCII 我们知道计算机是由外国人发明的,他们当时也没有考虑到 ...

  9. HTML基础 img标签 做一个图库

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

随机推荐

  1. Devexpress RaisePropertyChanged

    所有的重载设置字段作为参数传递到指定的值,而属性提高INotifyPropertyChanged.PropertyChanged事件. 如果一个字段已经成功地改变,setProperty方法中返回真. ...

  2. 模仿迅L看看<音频播放器> 实现点击进度条,跳转播放

    <Style x:Key="btnFallback" TargetType="{x:Type Button}"> <Setter Proper ...

  3. Java代码优化(长期更新)

    前言 2016年3月修改,结合自己的工作和平时学习的体验重新谈一下为什么要进行代码优化.在修改之前,我的说法是这样的: 就像鲸鱼吃虾米一样,也许吃一个两个虾米对于鲸鱼来说作用不大,但是吃的虾米多了,鲸 ...

  4. Java中, for循环经典例子

    循环的两种应用:穷举和迭代. break跳出整个循环 一.穷举:将所有可能的情况都走一遍,用if筛选出符合条件. 百鸡百钱: 一只公鸡1文钱,一只母鸡2文钱,一只小鸡半文钱,需要买100只鸡, 正好花 ...

  5. 3、Python字符串和循环

    1.while循环 #猜lucky_number = 6 #如果比6大,提示你猜的大了 #如果比6小,提示你猜的小了 #猜的等于6,提示Bingo #限制3次 lucky_num = 6 count ...

  6. Cats(2)- Free语法组合,Coproduct-ADT composition

    上篇我们介绍了Free类型可以作为一种嵌入式编程语言DSL在函数式编程中对某种特定功能需求进行描述.一个完整的应用可能会涉及多样的关联功能,但如果我们为每个应用都设计一套DSL的话,那么在我们的函数式 ...

  7. Java的关键字与标识符

    Java作为一门编程语言,与其他语言一样,有字符集.标识符.和关键字.变量.常量.语句等编程语言的基本要素. 1.关键字 abstract boolean break byte case catch ...

  8. Could not publish server configuration for Tomcat v6.0 Server at localhost.

    经常在使用tomcat服务器的时候 总会发生一些莫名其妙的错误. 就像下面这个错误: 在配置文件中存在多个/MyWeb的配置,导致不能发布服务. 错误信息: Could not publish ser ...

  9. discuz 3.x 核心文件class_core.php解析

    class_core.php是discuz 3.x的核心文件,几乎所有PHP脚本都有引用此文件初始化论坛运行环境.以下解析引用3.2版discuz. line 12-15:常量定义IN_DISCUZ: ...

  10. Web API初探

    前几天有位同事说web api中的接口参数为对象的时候不好接收,具体什么方式我忘记了,虽然本人以前并没有接触过这方面的知识,但是据说和MVC差不多的,今天小小的研究一下,我想应该是可以的. 直接新建一 ...