C#特性怎么定义
C#特性怎么定义
本篇内容主要讲解“C#特性怎么定义”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#特性怎么定义”吧!
一、什么是特性
特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义特性和自定义特性。
特性的语法如下:
[attribute(positional_parameters,name_parameter=value,...)]element
特性(Attribute)的名称和值是在方括号内规定的,放置在它所应用的元素之前。positional_parameters 规定必需的信息,name_parameter 规定可选的信息。
二、预定义特性
Obsolete特性
这个预定义特性标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。例如,当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为 obsolete(过时的)。
语法如下:
[Obsolete(message)][Obsolete(message,iserror)]
其中:
参数message,是一个字符串,描述项目为什么过时的原因以及该替代使用什么。
参数iserror,是一个布尔值。如果该值为 true,编译器应把该项目的使用当作一个错误。默认值是 false(编译器生成一个警告)。
请看下面的一个小例子:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{[Obsolete("请不要使用该类了,该类已经过时了,请使用什么代替")]publicclassStudent{publicintId{get;set;}publicstringName{get;set;}publicstringAccont{get;set;}publiclongQQ{get;set;}publicstringAnswer([Custom]stringname){return$"Thisis{name}";}}}
上面的例子中,在Student类上面使用了Obsolete特性来标注该类已经过时了。编译代码结果:
三、自定义特性
.Net 框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关。
创建并使用自定义特性包含四个步骤:
声明自定义特性
构建自定义特性
在目标程序元素上应用自定义特性
通过反射访问特性
1、声明自定义特性
在上面的例子中,使用F12查看Obsolete的定义:
从上面的截图中可以看出,.NET框架中的预定义特性是继承自Attribute类,所以要自定义一个特性,只需要该类继承自Attribute即可,下面定义一个Custom自定义特性:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{///<summary>///自定义Custom特性///</summary>publicclassCustomAttribute:Attribute{}}
注意:所有的特性默认以Attribute结尾,但声明的时候可以不以Attribute结尾。
2、构建自定义特性
每个特性必须至少有一个构造函数。必需的定位( positional)参数应通过构造函数传递。下面的代码演示了CustomAttribute类:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{///<summary>///自定义Custom特性///</summary>publicclassCustomAttribute:Attribute{///<summary>///无参构造函数///</summary>publicCustomAttribute(){}///<summary>///有参构造函数///</summary>///<paramname="id"></param>publicCustomAttribute(stringdescription){this.Description=description;}///<summary>///属性///</summary>publicstringDescription{get;set;}///<summary>///字段///</summary>publicstringRemark=null;publicvoidShow(){Console.WriteLine("ThisIsCustomAttribute");}}}
3、在目标程序元素上应用自定义特性
通过把特性放置在紧接着它的目标(类、方法、属性、字段等)上面,来应用该特性:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{[Obsolete("请不要使用该类了,该类已经过时了")][Custom("这是Custom自定义特性")]publicclassStudent{publicintId{get;set;}publicstringName{get;set;}publicstringAccont{get;set;}publiclongQQ{get;set;}publicstringAnswer([Custom]stringname){return$"Thisis{name}";}}}
注意:
1、如果在声明自定义特性的时候使用了Attribute结尾,那么应用自定义特性的时候可以把Attribute省略掉;如果声明的时候没有以Attribute结尾,那么应用自定义特性的时候就不能把Attribute省略掉。
2、默认情况下相同的特性只能应用一次,如果想应用多次特性,那么需要给特性添加AttributeUsage特性,CustomAttribute特性修改如下:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{///<summary>///自定义Custom特性///</summary>[AttributeUsage(AttributeTargets.All,AllowMultiple=true,Inherited=true)]publicclassCustomAttribute:Attribute{///<summary>///无参构造函数///</summary>publicCustomAttribute(){}///<summary>///有参构造函数///</summary>///<paramname="id"></param>publicCustomAttribute(stringdescription){this.Description=description;}///<summary>///属性///</summary>publicstringDescription{get;set;}///<summary>///字段///</summary>publicstringRemark=null;publicvoidShow(){Console.WriteLine("ThisIsCustomAttribute");}}}
其中,AttributeTargets是枚举值,F12转到定义可以查看AttributeTargets的所有枚举值:
AttributeTargets的枚举值表示Custom特性可以应用在哪些目标上面。例如:AttributeTargets的枚举值是Class,则表示CustomAttribute只能应用在类上面。这里枚举值是All,表示可以在任何类型上面使用该特性。默认情况下枚举值是All。
AllowMultiple表示该特性是否可以在类型上面多次使用:
这里AllowMultiple的值为true,表示可以在类型上面多次使用该特性。如果为false,则表示只能使用一次。默认情况下是false。
Inherited表示该特性是否可以由子类继承:
默认情况下Inherited为true。
这是在看Student类:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{[Obsolete("请不要使用该类了,该类已经过时了")][Custom("这是Custom自定义特性")]//使用有参构造[Custom()]//使用无参构造publicclassStudent{publicintId{get;set;}///<summary>///在属性上面使用Custom特性///</summary>[Custom("这是Name属性")]publicstringName{get;set;}publicstringAccont{get;set;}publiclongQQ{get;set;}///<summary>///在方法和参数上面使用Custom特性///</summary>///<paramname="name"></param>///<returns></returns>[Custom("这是Answer方法")]publicstringAnswer([Custom("这是方法参数")]stringname){return$"Thisis{name}";}}}
注意:如果一个类型上面多次使用了同一种特性,那么特性可以写在一起,中间用逗号隔开,例如上面的定义和下面的是同样的效果:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{[Obsolete("请不要使用该类了,该类已经过时了")][Custom("这是Custom自定义特性"),Custom,Custom(),Custom(Remark="备注")]publicclassStudent{publicintId{get;set;}///<summary>///在属性上面使用Custom特性///</summary>[Custom("这是Name属性")]publicstringName{get;set;}publicstringAccont{get;set;}publiclongQQ{get;set;}///<summary>///在方法、方法参数、方法的返回值上面使用Custom特性///</summary>///<paramname="name"></param>///<returns></returns>[Custom("这是Answer方法")]//方法上面应用特性[return:Custom()]//方法的返回值应用特性publicstringAnswer([Custom("这是方法参数")]stringname){return$"Thisis{name}";}}}
注意:在Web API中FromBaby和FromUri就是给方法的参数应用特性。
4、通过反射访问特性
定义一个Manager类来管理特性:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{///<summary>///管理特性///</summary>publicclassManager{publicstaticvoidShow(Studentstudent){//获取类型Typetype=typeof(Student);//或者使用student.GetType();//找到类型上面的特性type.IsDefined表示找类型上面的特性if(type.IsDefined(typeof(CustomAttribute),true))//检查有没有性能高{//GetCustomAttribute获取特性type.GetCustomAttribute表示找到类型上面定义的特性,表示调用构造函数创建一个CustomAttribute类型的对象CustomAttributeattribute=(CustomAttribute)type.GetCustomAttribute(typeof(CustomAttribute),true);//attribute.Description表示特性类里面的属性attribute.Remark表示特性类里面的字段Console.WriteLine($"{attribute.Description}_{attribute.Remark}");attribute.Show();}#region获取ID属性上面定义的特性//获取Id属性PropertyInfoproperty=type.GetProperty("Id");//检查Id属性上面是否定义了CustomAttribute特性if(property.IsDefined(typeof(CustomAttribute),true)){CustomAttributeattribute=(CustomAttribute)property.GetCustomAttribute(typeof(CustomAttribute),true);Console.WriteLine($"{attribute.Description}_{attribute.Remark}");attribute.Show();}#endregion#region获取Answer()方法上面定义的特性//获取Answer方法MethodInfomethod=type.GetMethod("Answer");if(method.IsDefined(typeof(CustomAttribute),true)){CustomAttributeattribute=(CustomAttribute)method.GetCustomAttribute(typeof(CustomAttribute),true);Console.WriteLine($"{attribute.Description}_{attribute.Remark}");attribute.Show();}#endregion#region获取参数定义的特性ParameterInfoparameter=method.GetParameters()[0];if(parameter.IsDefined(typeof(CustomAttribute),true)){CustomAttributeattribute=(CustomAttribute)parameter.GetCustomAttribute(typeof(CustomAttribute),true);Console.WriteLine($"{attribute.Description}_{attribute.Remark}");attribute.Show();}#endregion#region获取返回值定义的特性ParameterInforeturnParameter=method.ReturnParameter;if(returnParameter.IsDefined(typeof(CustomAttribute),true)){CustomAttributeattribute=(CustomAttribute)returnParameter.GetCustomAttribute(typeof(CustomAttribute),true);Console.WriteLine($"{attribute.Description}_{attribute.Remark}");attribute.Show();}#endregionstringresult=student.Answer("Tom");Console.WriteLine(result);}}}
Main()方法里面调用:
usingMyAttribute.Extension;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{classProgram{staticvoidMain(string[]args){Studentstudent=newStudent();student.Id=123;student.Name="time";//使用Manager类管理StudentManager.Show(student);Console.ReadKey();}}}
结果:
四、应用特性
场景一:用户状态的枚举值,定义的是英文的字段,需要输出中文含义。枚举定义如下:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///枚举类型用户状态///</summary>publicenumUserState{///<summary>///正常///</summary>Normal=0,///<summary>///冻结///</summary>Frozen=1,///<summary>///删除///</summary>Deleted=2}}
普通做法:根据枚举值进行判断,然后输出中文含义:
UserStateuserState=UserState.Normal;switch(userState){caseUserState.Normal:Console.WriteLine("正常");break;caseUserState.Frozen:Console.WriteLine("冻结");break;caseUserState.Deleted:Console.WriteLine("删除");break;}
这种写法违反开不原则,不利于以后的扩展,下面使用特性实现。
先定义Remark特性:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Reflection;namespaceMyAttribute.Extension{///<summary>///RemarkAttribute特性///</summary>publicclassRemarkAttribute:Attribute{privatestring_Remark=null;///<summary>///有参构造///</summary>///<paramname="remark"></param>publicRemarkAttribute(stringremark){this._Remark=remark;}publicstringGetRemark(){return_Remark;}}}
UserState枚举修改如下:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///枚举类型用户状态///</summary>publicenumUserState{///<summary>///正常///</summary>[Remark("正常")]Normal=0,///<summary>///冻结///</summary>[Remark("冻结")]Frozen=1,///<summary>///删除///</summary>[Remark("删除")]Deleted=2}}
对Enum类型进行扩展:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{publicstaticclassEnumExtension{///<summary>///Enum的扩展方法,静态类、静态方法第一个参数前面添加this关键字///</summary>///<paramname="value"></param>///<returns></returns>publicstaticstringGetRemark(thisEnumvalue){//获取类型Typetype=value.GetType();//获取字段FieldInfofield=type.GetField(value.ToString());//判断字段上面是否定义了RemarkAttribute特性if(field.IsDefined(typeof(RemarkAttribute))){//创建实例RemarkAttributeattribute=(RemarkAttribute)field.GetCustomAttribute(typeof(RemarkAttribute));//返回RemarkAttribute特性里面的GetRemark()方法returnattribute.GetRemark();}else{returnvalue.ToString();}}}}
Main()方法里面调用:
usingMyAttribute.Extension;usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute{classProgram{staticvoidMain(string[]args){Studentstudent=newStudent();student.Id=123;student.Name="time";//使用Manager类管理Student//Manager.Show(student);UserStateuserState=UserState.Normal;//switch(userState)//{//caseUserState.Normal://Console.WriteLine("正常");//break;//caseUserState.Frozen://Console.WriteLine("冻结");//break;//caseUserState.Deleted://Console.WriteLine("删除");//break;//}Console.WriteLine(userState.GetRemark());Console.ReadKey();}}}
结果:
场景二、做数据校验
Student中有QQ这个属性,范围是10000-999999999999,校验QQ属性的值在这个范围区间内。
1、定义一个RangeAttribute特性,用来验证属性范围
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///定义LongAttribute特性,并且特性只能应用在字段和属性上面///</summary>[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property)]publicclassRangeAttribute:Attribute{///<summary>///最小范围///</summary>privatelong_MinRange=0;///<summary>///最大范围///</summary>privatelong_MaxRange=0;publicRangeAttribute(longmin,longmax){this._MinRange=min;this._MaxRange=max;}///<summary>///检查属性范围///</summary>///<paramname="value"></param>///<returns></returns>publicboolCheck(objectvalue){if(value!=null&&!string.IsNullOrWhiteSpace(value.ToString())){if(long.TryParse(value.ToString(),outlongIResult)){if(IResult>this._MinRange&&IResult<this._MaxRange){returntrue;}}}returnfalse;}}}
2、在Student类的QQ属性上面应用特性
[Range(10001,999999999999)]publiclongQQ{get;set;}
3、对Object类型进行扩展
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///object类型的验证扩展///</summary>publicstaticclassObjectExtension{///<summary>///对object类型扩展一个Validate的方法///</summary>///<paramname="obj"></param>///<paramname="msg">输出参数,输出验证信息。如果验证通过,输出空字符串;如果验证不通过,输出具体信息</param>///<returns></returns>publicstaticboolValidate(thisobjectobj,outstringmsg){//获取类型Typetype=obj.GetType();//获取属性PropertyInfo[]propertyInfos=type.GetProperties();foreach(PropertyInfopropinpropertyInfos){if(prop.IsDefined(typeof(LongAttribute))){LongAttributeattribute=(LongAttribute)prop.GetCustomAttribute(typeof(LongAttribute));if(!attribute.Check(prop.GetValue(obj))){msg=prop.Name+"检查失败";returnfalse;}}}msg="";returntrue;}}}
4、在Manager类里面使用Validate扩展方法
//验证stringmsg=string.Empty;booltfResult=student.Validate(outmsg);if(!tfResult){Console.WriteLine(msg);}
5、在Main()方法里面调用
Studentstudent=newStudent();student.Id=123;student.Name="time";student.QQ=9999;//使用Manager类管理StudentManager.Show(student);
结果:
如果这时候Student里面增加了Name属性,并且要验证Name属性的长度,这时需要增加一个验证属性长度的特性:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///验证长度的特性,只能应用于字段和属性上面///</summary>[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property)]publicclassLengthAttribute:Attribute{///<summary>///最小长度///</summary>privateint_MinLength=0;///<summary>///最大长度///</summary>privateint_MaxLength=0;publicLengthAttribute(intmin,intmax){this._MinLength=min;this._MaxLength=max;}///<summary>///检查属性长度///</summary>///<paramname="value"></param>///<returns></returns>publicboolCheck(objectvalue){if(value!=null&&!string.IsNullOrWhiteSpace(value.ToString())){if(long.TryParse(value.ToString(),outlongIResult)){if(IResult>this._MinLength&&IResult<this._MaxLength){returntrue;}}}returnfalse;}}}
在Student类的Name属性上面应用LengthAttribute特性:
[Length(5,10)]publicstringName{get;set;}
在ObjectExtension里面增加长度的验证:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///object类型的验证扩展///</summary>publicstaticclassObjectExtension{///<summary>///对object类型扩展一个Validate的方法///</summary>///<paramname="obj"></param>///<paramname="msg">输出参数,输出验证信息。如果验证通过,输出空字符串;如果验证不通过,输出具体信息</param>///<returns></returns>publicstaticboolValidate(thisobjectobj,outstringmsg){//获取类型Typetype=obj.GetType();//获取属性PropertyInfo[]propertyInfos=type.GetProperties();foreach(PropertyInfopropinpropertyInfos){//检查属性上面是否定义了RangeAttribute特性if(prop.IsDefined(typeof(RangeAttribute))){RangeAttributeattribute=(RangeAttribute)prop.GetCustomAttribute(typeof(RangeAttribute));if(!attribute.Check(prop.GetValue(obj))){msg=string.Format($"属性{prop.Name}范围检查失败");returnfalse;}}//检查属性上面是否定义了LengthAttribute特性if(prop.IsDefined(typeof(LengthAttribute))){LengthAttributeattribute=(LengthAttribute)prop.GetCustomAttribute(typeof(LengthAttribute));if(!attribute.Check(prop.GetValue(obj))){msg=string.Format($"属性{prop.Name}长度检查失败");returnfalse;}}}msg="";returntrue;}}}
最后在Main()方法里面调用:
Studentstudent=newStudent();student.Id=123;student.Name="time";//使用Manager类管理StudentManager.Show(student);
结果:
仔细查看ObjectExtension扩展类:每增加一个特性,扩展方法里面就要增加一段相同的代码(只是特性的类型不同),那么能不能做到增加特性,而这里不需要修改呢?请看下面的修改:
1、定义一个抽象类继承自Attribute,里面有一个抽象的Check()方法,定义如下:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///抽象基类,继承自Attribute///</summary>publicabstractclassAbstractValidateAttribute:Attribute{publicabstractboolCheck(objectvalue);}}
2、修改RangeAttribute和LengthAttribute两个特性类,都继承自AbstractValidateAttribute基类
RangeAttribute类:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///定义LongAttribute特性,并且特性只能应用在字段和属性上面///</summary>[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property)]publicclassRangeAttribute:AbstractValidateAttribute{///<summary>///最小范围///</summary>privatelong_MinRange=0;///<summary>///最大范围///</summary>privatelong_MaxRange=0;publicRangeAttribute(longmin,longmax){this._MinRange=min;this._MaxRange=max;}///<summary>///重写基类方法检查属性范围///</summary>///<paramname="value"></param>///<returns></returns>publicoverrideboolCheck(objectvalue){if(value!=null&&!string.IsNullOrWhiteSpace(value.ToString())){if(long.TryParse(value.ToString(),outlongIResult)){if(IResult>this._MinRange&&IResult<this._MaxRange){returntrue;}}}returnfalse;}}}
LengthAttribute类:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///验证长度的特性,只能应用于字段和属性上面///</summary>[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property)]publicclassLengthAttribute:AbstractValidateAttribute{///<summary>///最小长度///</summary>privateint_MinLength=0;///<summary>///最大长度///</summary>privateint_MaxLength=0;publicLengthAttribute(intmin,intmax){this._MinLength=min;this._MaxLength=max;}///<summary>///重写基类方法检查属性长度///</summary>///<paramname="value"></param>///<returns></returns>publicoverrideboolCheck(objectvalue){if(value!=null&&!string.IsNullOrWhiteSpace(value.ToString())){if(long.TryParse(value.ToString(),outlongIResult)){if(IResult>this._MinLength&&IResult<this._MaxLength){returntrue;}}}returnfalse;}}}
3、修改ObjectExtension扩展类
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Tasks;namespaceMyAttribute.Extension{///<summary>///object类型的验证扩展///</summary>publicstaticclassObjectExtension{///<summary>///对object类型扩展一个Validate的方法///</summary>///<paramname="obj"></param>///<paramname="msg">输出参数,输出验证信息。如果验证通过,输出空字符串;如果验证不通过,输出具体信息</param>///<returns></returns>publicstaticboolValidate(thisobjectobj,outstringmsg){//获取类型Typetype=obj.GetType();//获取属性PropertyInfo[]propertyInfos=type.GetProperties();foreach(PropertyInfopropinpropertyInfos){//判断属性上面是否定义了AbstractValidateAttribute特性if(prop.IsDefined(typeof(AbstractValidateAttribute),true)){//属性上面可能会定义多个特性,所以这里使用数组object[]attributeArray=prop.GetCustomAttributes(typeof(AbstractValidateAttribute),true);foreach(AbstractValidateAttributeattributeinattributeArray){if(!attribute.Check(prop.GetValue(obj))){msg=string.Format($"属性{prop.Name}检查失败");returnfalse;}}}////检查属性上面是否定义了RangeAttribute特性//if(prop.IsDefined(typeof(RangeAttribute)))//{//RangeAttributeattribute=(RangeAttribute)prop.GetCustomAttribute(typeof(RangeAttribute));//if(!attribute.Check(prop.GetValue(obj)))//{//msg=string.Format($"属性{prop.Name}范围检查失败");//returnfalse;//}//}////检查属性上面是否定义了LengthAttribute特性//if(prop.IsDefined(typeof(LengthAttribute)))//{//LengthAttributeattribute=(LengthAttribute)prop.GetCustomAttribute(typeof(LengthAttribute));//if(!attribute.Check(prop.GetValue(obj)))//{//msg=string.Format($"属性{prop.Name}长度检查失败");//returnfalse;//}//}}msg="";returntrue;}}}
4、运行结果:
经过上面的修改以后,如果以后要新增一个特性,那么该特性只需要在本类中重写基类的Check()方法即可,而不需要在修改ObjectExtension扩展类。
到此,相信大家对“C#特性怎么定义”有了更深的了解,不妨来实际操作一番吧!这里是恰卡编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
推荐阅读
-
polyfills怎么按需加载
polyfills怎么按需加载本篇内容主要讲解“polyfills...
-
C#数据类型怎么实现背包、队列和栈
-
C#怎么实现冒泡排序和插入排序算法
C#怎么实现冒泡排序和插入排序算法这篇文章主要讲解了“C#怎么实现...
-
C#如何实现希尔排序
-
C#如何实现归并排序
-
C#怎么使用符号表实现查找算法
-
C#类的静态成员怎么用
C#类的静态成员怎么用这篇“C#类的静态成员怎么用”文章的知识点大...
-
C#的静态函数怎么用
C#的静态函数怎么用这篇文章主要讲解了“C#的静态函数怎么用”,文...
-
C#中的析构函数怎么用
C#中的析构函数怎么用这篇文章主要讲解了“C#中的析构函数怎么用”...
-
怎么用CZGL.ProcessMetrics监控.NET应用