前言
好记性不如烂笔头,感觉记性越来越差了,还是得靠记下来才靠谱,方便以后自己查阅
本文章主要记录一下C#特性的使用,主要是通过特性获取枚举的描述,通过特性对实体进行验证
一、通过特性获取枚举
首先创建一个简单的枚举
。
public enum GenderEnum
{
/// <summary>
/// 男性
/// </summary>
[EnumRemark("男性")]
Man = 0,
/// <summary>
/// 女性
/// </summary>
[EnumRemark("女性")]
Woman = 1,
}
该枚举的字段上有一个自定义的特性 EnumRemarkAttribute
,代码如下:
/// <summary>
/// 枚举描述特性
/// </summary>
[AttributeUsage(AttributeTargets.Field,AllowMultiple =true,Inherited =true)]
public class EnumRemarkAttribute :Attribute
{
public string Remark { get; set; }
public EnumRemarkAttribute(string remark)
{
this.Remark = remark;
}
}
该特性包括一个属性,一个带参的构造函数,
顶部有一个特性AttributeUsage
,它主要的作用就是对我们创建的自定义特性进行 一些约束,
具体的作用可以参考 链接: https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/attributes/general.
新建一个扩展方法来获取枚举上的描述
/// <summary>
/// 枚举描述特性扩展方法
/// </summary>
public static class EnumRemarkAttributeExtension
{
/// <summary>
/// 获取枚举描述
/// </summary>
/// <param name="enumValue"></param>
/// <returns></returns>
public static string GetRemark(this Enum enumValue)
{
var type = enumValue.GetType();
FieldInfo fileInfo = type.GetField(enumValue.ToString());
if (fileInfo != null)
{
if (fileInfo.IsDefined(typeof(EnumRemarkAttribute), true))
{
var att = (EnumRemarkAttribute)fileInfo.GetCustomAttribute(typeof(EnumRemarkAttribute));
return att.Remark;
}
}
return string.Empty;
}
}
简单运行一下
//获取枚举描述
Console.WriteLine(GenderEnum.Man.GetRemark());
Console.WriteLine(GenderEnum.Woman.GetRemark());
运行结果如下图:
二、通过特性对实体进行验证
新建实体:
public class Student
{
public int ID { get; set; }
[NonEmptyValidate("学生姓名不能为空")]
[MaxLengthValidate(5)]
public string Name { get; set; }
public string StudentNo { get; set; }
public string MobilePhone { get; set; }
[EmailValidate]
public int Email { get; set; }
public GenderEnum Gender { get; set; }
}
新建自定义验证基类
/// <summary>
/// 自定义验证基类
/// </summary>
[AttributeUsage(AttributeTargets.Property,AllowMultiple =true,Inherited =true)]
public abstract class BaseValidateAttribute : Attribute
{
protected abstract string ErrMessage { get; set; }
public abstract ValidateResult Validate(object value);
}
新建的验证特性都继承自BaseValidateAttribute抽象类
/// <summary>
/// 非空验证
/// </summary>
public class NonEmptyValidateAttribute : BaseValidateAttribute
{
protected override string ErrMessage { get; set; } = "该项不能为空";
public NonEmptyValidateAttribute()
{
}
public NonEmptyValidateAttribute(string errMsg)
{
this.ErrMessage = errMsg;
}
public override ValidateResult Validate(object value)
{
var result = new ValidateResult();
result.IsValid = !(value is null);
if (!result.IsValid)
{
result.ErrMessage = ErrMessage;
}
return result;
}
}
最大长度验证
/// <summary>
/// 最大长度
/// </summary>
public class MaxLengthValidateAttribute : BaseValidateAttribute
{
private int MaxLenth { get; set; }
protected override string ErrMessage { get; set; } = "该项长度不能大于";
public MaxLengthValidateAttribute(int maxLength, string errMsg = "")
{
this.MaxLenth = maxLength;
if (!string.IsNullOrWhiteSpace(errMsg))
{
this.ErrMessage = errMsg;
}
}
public override ValidateResult Validate(object value)
{
var result = new ValidateResult();
if (value != null)
{
result.IsValid = value.ToString().Length <= MaxLenth;
if (!result.IsValid)
{
result.ErrMessage = $"{ErrMessage}{MaxLenth}";
}
}
return result;
}
}
邮箱格式验证
public class EmailValidateAttribute : BaseValidateAttribute
{
protected override string ErrMessage { get; set; } = "邮箱格式错误";
private string regExp = @"^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$";
public EmailValidateAttribute(string errMsg = "")
{
if (!string.IsNullOrWhiteSpace(errMsg))
{
this.ErrMessage = errMsg;
}
}
public override ValidateResult Validate(object value)
{
var result = new ValidateResult();
if (!IsMatch(value?.ToString(),regExp,true,false))
{
result.IsValid = false;
result.ErrMessage = ErrMessage;
}
return result;
}
/// <summary>
/// 验证字符串是否匹配正则表达式描述的规则
/// </summary>
/// <param name="inputStr">待验证的字符串</param>
/// <param name="patternStr">正则表达式字符串</param>
/// <param name="ifIgnoreCase">匹配时是否不区分大小写</param>
/// <param name="ifValidateWhiteSpace">是否验证空白字符串</param>
/// <returns>是否匹配</returns>
public bool IsMatch(string inputStr, string patternStr, bool ifIgnoreCase, bool ifValidateWhiteSpace)
{
if (!ifValidateWhiteSpace && string.IsNullOrWhiteSpace(inputStr))
return false;//如果不要求验证空白字符串而此时传入的待验证字符串为空白字符串,则不匹配
Regex regex = null;
if (ifIgnoreCase)
regex = new Regex(patternStr, RegexOptions.IgnoreCase);//指定不区分大小写的匹配
else
regex = new Regex(patternStr);
return regex.IsMatch(inputStr);
}
}
新建一个扩展方法
public static class ValidateAttributeExtension
{
public static ValidateResult Validate<T>(this T t) where T : new()
{
var result = new ValidateResult()
{
IsValid = true
};
var type = typeof(T);
foreach (PropertyInfo property in type.GetProperties())
{
if (property.IsDefined(typeof(BaseValidateAttribute), true))
{
var thisValue = property.GetValue(t);
var atrributes = property.GetCustomAttributes(typeof(BaseValidateAttribute));
foreach (BaseValidateAttribute atrribute in atrributes)
{
var validateResult = atrribute.Validate(thisValue);
if (!validateResult.IsValid)
{
result.IsValid = false;
result.ErrMessage += validateResult.ErrMessage+",";
}
}
if (result.ErrMessage.Length > 0)
{
result.ErrMessage = result.ErrMessage.Remove(result.ErrMessage.Length - 1);
}
}
}
return result;
}
}
这些功能在.NET系统库都是有的,写下来主要就是记录下特性的使用方式和技巧,在实际工作中可以通过这种方式的使用来扩展一些自己的方法,减少一些工作量和代码的重复编写.