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高 ...
随机推荐
- django中使用memcache的一些注意事项
最近写django项目时在保存验证码方面要用到memcached,于是便查看了一些教程进行操作,结果确遇到了一系列问题,以下是一些容易遇到的雷区: 1.windows下memcached安装: -wi ...
- Anfora 自动装载类
1.目录结构 + Anfora | + Autoload | - ClassLoader.php | - Autoload.php - autoload.php 2.注册类加载器 src/Anfora ...
- eclipse新建的项目,也添加到tomcat上了,地址栏访问的时候就是访问不到。。。怎么办
其实是可以访问的,目前我遇到以下两种可能出现这种现象的原因: 1.这个项目在你写的过程中改了名字,这样你访问改后的名字是不行的,需要在下图,也就是server服务器的server.xml文件中修改访问 ...
- 第4周小组作业:WordCount优化
Github项目地址:https://github.com/chaseMengdi/wcPro stage1:代码编写+单元测试 PSP表格 PSP2.1 PSP阶段 预估耗时(分钟) 实际耗时(分 ...
- Java工具eclipse控制台console输出乱码问题
捣鼓了一下午,终于tm解决! 我的是Scanner读入,println打印乱码问题. 首先在cmd窗口运行java,是没有乱码问题的,这证明了在cmd窗口时Scanner输入的和println打印的编 ...
- NodeJs在windows上安装配置测试
Node.js简介简单的说 Node.js 就是运行在服务端的 JavaScript.Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个 ...
- 每天学点SpringCloud(十三):SpringCloud-Stream整合RabbitMQ
我们知道,当微服务越来越来多的时候,仅仅是feign的http调用方式已经满足不了我们的使用场景了.这个时候系统就需要接入消息中间件了.相比较于传统的Spring项目.SpringBoot项目使用消息 ...
- UnicodeDecodeError:utf-8codeccantdecodebyte0xb9inposition0:invalidstartbyte
相信这个问题大家都会以为是编码的问题,当然原本我也以为是编码问题! 然后试了各种方案!都是以失败告终! 哈哈哈,后来解决了,原来真是闹了个大笑话............ 这是因 ...
- while(true)应用之 实现自己的消息队列
早些时候,一直有个疑问,就是比如你从前端发一个操作之后,后台为什么能够及时处理你的东西呢?当然了,我说的不是,服务器为什么能够立即接收到你的请求之类高大上的东西.而是,假设你用异步去做一个事情,而后台 ...
- Linux(Centos平台)RabbitMQ消息中间件服务器搭建
本篇结合接口测试平台部署来讲,不了解的请先查看我的另一篇文档,HttpRunnerManager接口测试平台部署在服务器上(Centos + python3.6 + Mysql5.7 + uwsgi ...