上篇文章“.NET无处不在的特性(Attribute)1-探究”讲了特性的探究, 这篇文章介绍自定义特性。
在以前传统的开发中,后端也需要做很多的验证,比如不为空验证、长度验证、电话号码验证等,那么我们还是以上面的案例简单的自定义特性。
public class RequiredAttribute : Attribute{}
[AttributeUsage(AttributeTargets.All|AttributeTargets.Class//可以指定多个,AllowMultiple=true,Inherited =false)]
public class RequiredAttribute : Attribute{//我们这里参数用object,便于通用性,但是如果是字符串需要特殊处理。public bool Verification(object proValue){if (proValue == null){return false;}elsereturn true;}}//这里为了传递字符的限制长度,可以用构造函数传入参数,使用特性也需要加上参数public class StringLengthAttribute : Attribute{int _min = 0;int _max = 10;//参数默认值防止参数报错public StringLengthAttribute(int max = 10, int min = 0){_min = min;_max = max;}public bool Verification(object proValue){if (proValue == null|| proValue.ToString().Length < this._min|| proValue.ToString().Length > this._max)return falseelsereturn true;}}//使用
[Required]//非空验证[StringLength(20,3)]//字数长度验证public string name { get; set; }
public static bool IsVerification(this object obj){Type type = obj.GetType();//反射出类型var pro = type.GetProperties();//获取属性foreach (var property in pro){//是否包含属性if (property.IsDefined(typeof(RequiredAttribute), true)){var propertyValue = property.GetValue(obj);//获取属性值//实例化验证类var attribute = property.GetCustomAttribute<RequiredAttribute>();//调用验证方法bool rel = attribute.Verification(propertyValue);if (!rel){return false;}}if (property.IsDefined(typeof(StringLengthAttribute), true)){var propertyValue = property.GetValue(obj);var attribute = property.GetCustomAttribute<StringLengthAttribute>();bool rel = attribute.Verification(propertyValue);if (!rel){return false;}}}return true;}
调用如下代码:
Customer customer = new Customer(){id = 2,name = "张学友",age = 52,email = "zxy@net.cn"};var rel= customer.IsVerification();//结果返回为true,如果name赋值为空则返回为false
5、代码重构和优化
重构特性验证类
验证的特性可能有多个,我们可以把验证的特性抽象化,这样可以统一配置、可以在父类创立公共方法等,如下。
/// <summary>///抽象类,可以配置特性的属性,/// </summary>[AttributeUsage(AttributeTargets.All,AllowMultiple=true,Inherited =false)]public abstract class AbstractAttribute: Attribute{public abstract bool Verification(object proValue);}public class RequiredAttribute : AbstractAttribute{//我们这里参数用object,便于通用性,但是如果是字符串需要特殊处理。public override bool Verification(object proValue){if (proValue == null){return false;}elsereturn true;}//这里为了传递字符的限制长度,可以用构造函数传入参数,使用特性也需要加上参数public class StringLengthAttribute : AbstractAttribute{int _min = 0;int _max = 10;public StringLengthAttribute(int max = 10, int min = 0){_min = min; _max = max;}public override bool Verification(object proValue){if (proValue == null|| proValue.ToString().Length < this._min|| proValue.ToString().Length > this._max)return false;elsereturn true;}}}
优化调用的验证方法
反射的验证方法如果有多个那么我们需要判断多次,还需要输入特性类名来反射方法,我们可以把验证方法改成通用的,而且通过反射来获取特性验证类的名称,如下:
public static bool IsVerification(this object obj){Type type = obj.GetType();//反射出类型var pro = type.GetProperties();//获取属性foreach (var property in pro){var Attributess = property.GetCustomAttributes();foreach (var item in Attributess){if (property.IsDefined(item.GetType(), true)){object[] propertyValues = { property.GetValue(obj) };var funcs = ((System.Reflection.TypeInfo)item.GetType()).DeclaredMethods;foreach (MethodInfo item2 in funcs){var rel= item2.Invoke(item, propertyValues);if (!(bool)rel){ return (bool)rel; }}}}}return true;}
上面的的重构和优化还有空间,比如反射效率问题,大家可以留言发表自己的重构优化建议。
源码:https://pan.baidu.com/s/1yC3uz8sMzq38oz_BwBNfFA?pwd=o113
提取码:o113
结语
这篇文章写了3天终于写完了,主要介绍了特性和自定义特性及优化。本文通过特性优化用到了oop的思想。写作水平有限,希望本文对大家学习和工作有一定参考价值,谢谢大家的支持。