c#中的特性Attribute
一:特性是什么?特性怎么创建怎么使用?
这一章节,我想谈谈c#的特性方面的知识,特性大家在工作开发中都很熟悉,比如我们经常见到的

/// <summary>
/// 是给枚举用 提供一个额外信息
/// AllowMultiple特性影响编译器,AttributeTargets修饰的对象 AllowMultiple:能否重复修饰 Inherited:是否可继承
/// 可以指定属性和字段
/// </summary>
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field,AllowMultiple =true,Inherited =true)]
public class RemarkAttribute : Attribute
{
public RemarkAttribute()
{
}
public RemarkAttribute(string remark)
{
this.Remark = remark;
}
public string Description; //字段
public string Remark { get; private set; }
}
然后特性类上面的AttributeUsage也是一个特性,具体的用处见上面的注释解释,特性创建好了,我们可以创建一个实体,然后再实体的字段上面使用这个特性,具体如下:
    [Remark("用户状态")]
    public enum UserState
    {
        /// <summary>
        /// 正常
        /// </summary>
        [Remark("正常")]
        Normal = ,
        /// <summary>
        /// 冻结
        /// </summary>
        [Remark("冻结")]
        Frozen = ,
        /// <summary>
        /// 删除
        /// </summary>
        [Remark("删除")]
        Deleted =
    }
因为AttributeTargets.Enum标识这个特性可以放在枚举上面,那我们上面那种代码也是完全被允许的,此外,AttributeTargets如果不写,则默认是全部都可以使用的!特性创建和特性标识已经准备好了,然而怎么使特性生效呢?这个还是需要我们写代码来实现的
public static class RemarkExtend
{
/// <summary>
/// 扩展方法
/// </summary>
/// <param name="enumValue"></param>
/// <returns></returns>
public static string GetRemark(this Enum enumValue)
{
Type type = enumValue.GetType();
FieldInfo field = type.GetField(enumValue.ToString());
if (field.IsDefined(typeof(RemarkAttribute), true))
{
RemarkAttribute remarkAttribute = (RemarkAttribute)field.GetCustomAttribute(typeof(RemarkAttribute));
return remarkAttribute.Remark;
}
else
{
return enumValue.ToString();
}
}
}
使特性的生效的代码已经写好了,然后我们如果想要获得一个枚举的中文名字可以通过下面调用
UserState userState = UserState.Normal;
Console.WriteLine(userState.GetRemark());
这样我们就可以随心所欲的获取到这个枚举的中文备注了,没有使用特性之前,我们想要获取到枚举的中文备注,一般会只能写死判断,如下:
UserState userState = UserState.Normal;
if (userState == UserState.Normal)
{
Console.WriteLine("正常状态");
}
else if (userState == UserState.Frozen)
{
Console.WriteLine("冻结状态");
}
else
{
Console.WriteLine("删除状态");
}
然后一旦要修改状态名字,则代码也随着修改,这就会导致维护比较困难,如果使用了特性,则会用到的地方不需要太关注这些文字,只需要调用,然后修改的时候,只需要修改枚举上面的文字即可,极其容易维护!
二:特性的运用范围
特性运用范围极其广,框架中我们看到上面的总结就晓得了,下面的我总结了以下几个地方也可以使用特性
1:数据展示 不想展示属性名字,而是用中文描述
2:想指定哪个是主键,哪个是自增
3:别名 数据库里面叫A 程序是B,怎么映射等
然后特性还可以校验一些数据字段等,下面我写个例子,以便更加容易理解:
1:先创建数据校验的特性
public abstract class AbstractValidateAttribute : Attribute
{
public abstract bool Validate(object oValue);
} public class LongValidateAttribute : AbstractValidateAttribute
{
private long _lMin = ;
private long _lMax = ;
public LongValidateAttribute(long lMin, long lMax)
{
this._lMin = lMin;
this._lMax = lMax;
} public override bool Validate(object oValue)
{
return this._lMin < (long)oValue && (long)oValue < this._lMax;
}
}
public class RequirdValidateAttribute : AbstractValidateAttribute
{
public override bool Validate(object oValue)
{
return oValue != null;
}
}
2:再一个实体类上面的字段增加特性
public class Student
{ [RequirdValidate]
public int Id { get; set; } [LongValidate(,)]//还有各种检查
public string Name { get; set; }
[LongValidate(, )]
public string Accont { get; set; } /// <summary>
/// 10001~999999999999
/// </summary>
[LongValidate(, )]
public long QQ { get; set; } }
3:写下面的方法,使特性生效
public class DataValidate
{
public static bool Validate<T>(T t)
{
Type type = t.GetType();
//IsDefined 是判断,不会调用构造函数
//if (type.IsDefined(typeof(AbstractValidateAttribute), true))
//{
// //调用构造函数
// var oAttributeArray = type.GetCustomAttributes(typeof(AbstractValidateAttribute), true);
// foreach (var item in oAttributeArray)
// { // }
//}
//foreach (var method in type.GetMethods())
//{
// if (method.IsDefined(typeof(AbstractValidateAttribute), true))
// {
// object item = method.GetCustomAttributes(typeof(AbstractValidateAttribute), true)[0];
// AbstractValidateAttribute attribute = item as AbstractValidateAttribute;
// //if (!attribute.Validate(method.GetValue(t)))
// //{
// // result = false;
// // break;
// //}
// }
//}
bool result = true;
foreach (var prop in type.GetProperties())
{
if (prop.IsDefined(typeof(AbstractValidateAttribute), true))
{
object item = prop.GetCustomAttributes(typeof(AbstractValidateAttribute), true)[];
AbstractValidateAttribute attribute = item as AbstractValidateAttribute;
if (!attribute.Validate(prop.GetValue(t)))
{
result = false;
break;
}
}
}
return result;
}
}
4:应用判断时如下:
Student student = new Student();
student.Id = ;
student.Name = "MrSorry";
student.QQ = ;
var result = DataValidate.Validate(student);
这样就完成了数据校验,特性校验的特点,总结得到了如下三点:
1:可以校验多个属性
2:可以支持多重校验
3:支持规则的随意扩展
运用了这个特性校验后,就不用再每个地方再分别写校验的逻辑,简单易用!
c#中的特性Attribute的更多相关文章
- C#中的特性 (Attribute) 入门 (二)
		C#中的特性 (Attribute) 入门 (二) 接下来我们要自己定义我们自己的特性,通过我们自己定义的特性来描述我们的代码. 自定义特性 所有的自定义特性都应该继承或者间接的继承自Attribut ... 
- C#中的特性 (Attribute) 入门 (一)
		C#中的特性 (Attribute) 入门 (一) 饮水思源 http://www.cnblogs.com/Wind-Eagle/archive/2008/12/10/1351746.html htt ... 
- c#核心基础 - 浅谈 c# 中的特性 Attribute)
		特性(Attribute)是用于在运行时传递程序中各种元素(比如类.方法.结构.枚举.组件等)的行为信息的声明性标签.可以通过使用特性向程序添加声明性信息.一个声明性标签是通过放置在它所应用的元素前面 ... 
- .net中的特性
		本文来之:http://hi.baidu.com/sanlng/item/afa31eed0a383e0e570f1d3e 在一般的应用中,特性(Attribute,以称为属性)好像被使用的不是很多. ... 
- [C#] 剖析 AssemblyInfo.cs - 了解常用的特性 Attribute
		剖析 AssemblyInfo.cs - 了解常用的特性 Attribute [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5944391.html 序 ... 
- [C#] C# 知识回顾 - 特性 Attribute
		C# 知识回顾 - 特性 Attribute [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5911289.html 目录 特性简介 使用特性 特性 ... 
- C# 知识特性 Attribute
		C#知识--获取特性 Attribute 特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集.类型.方法.属性等)相关联.特性与程序实体关联后,可在运行时使用"反射"查询 ... 
- C#中的 特性 详解(转载)
		本篇幅转载于:http://www.cnblogs.com/rohelm/archive/2012/04/19/2456088.html C#中特性详解 特性提供了功能强大的方法,用于将元数据或声明信 ... 
- 区分元素特性attribute和对象属性property
		× 目录 [1]定义 [2]共有 [3]例外[4]特殊[5]自定义[6]混淆[7]总结 前面的话 其实attribute和property两个单词,翻译出来都是属性,但是<javascript高 ... 
随机推荐
- ubuntu安装苹果Windows以及微软雅黑consolas字体
			ubuntu安装苹果Windows以及微软雅黑consolas字体 ubuntu安装苹果字体 wget http://drive.noobslab.com/data/Mac/macfonts.zip ... 
- js打断点
			F12打开调试器 资源sources 找到就是文件 选中需要打断点的行 获得段短点的值:将断点向后执行一步(页面提示的桥状小图标),然后选中上一步需要打断点的值,悬浮在上 ... 
- 下载、安装JDK并配置JDK的环境变量
			概念简介: JDK:(Java Development Kit)Java语言的软件开发工具包,它包含了Java程序的开发工具和Java程序的运行环境JRE: JRE:(Java Runtime Env ... 
- Vue route部分简单高级用法
			一改变页面title的值 在开发时常常需要在切换到不同页面时改变浏览器的title值,那么我们就可以在定义路由的时候通过配置 meta 属性 来改变title值. import Vue from ... 
- 疑难杂症:Java中Scanner连续获取int和String型发生错误.
			使用Scanner类获取输入,连续获取int类型和String类型数据时候,发生错误. Scanner sc = new Scanner(System.in); System.out.println( ... 
- 在windows上安装wamp时遇到apache无法启动,图标为橙色
			1.首先测试端口号是否被占用,如果端口号被占用,修改相对应文件的端口号,修改端口号的方法网上很容易搜到. 2.如果端口号没有被占用,cd到httpd.exe目录下,查看错误原因,这里我显示的错误是ht ... 
- MySQL--REPLACE INTO与自增
			##=====================================================================##测试环境:MySQL版本:MySQL 5.7.19复制 ... 
- 《Tornado介绍》—— 读后总结
- .net的服务转移
			问题: 服务器换新,但是本来服务器部署了一些window服务,需要迁移过来 解决过程: 百度了估计几百页了,之前因为老机器挂了,写这个代码布服务的人也早就不在了,所以自己闷头苦找,一个java初级程序 ... 
- Redis 指令 学习笔记
			Redis 什么是Redis redis是一种nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,还提供了多个语言的API,操作比较方便 安装re ... 
