上篇文章“.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;
}
else
return 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 false
else
return 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;
}
else
return 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;
else
return 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的思想。写作水平有限,希望本文对大家学习和工作有一定参考价值,谢谢大家的支持。