属性(Property)+ 反射(Reflection) 的实战案例
下面是一个完整的基于 属性(Property)+ 反射(Reflection) 的实战场景示例,我们将构建一个:
✅ 轻量级的数据模型校验框架:
通过属性上的自定义特性(Attribute),结合反射自动扫描并验证字段是否符合规则(如非空、长度、范围等)。
示例功能目标
- 使用属性定义实体类字段。
- 自定义验证 Attribute:如
[Required]、[StringLength]。 - 通过反射自动校验这些属性。
- 输出验证结果。
一、目录结构(类划分)
ValidationDemo/
│
├── Attributes/
│ ├── RequiredAttribute.cs
│ └── StringLengthAttribute.cs
│
├── Validators/
│ └── ObjectValidator.cs
│
├── Models/
│ └── User.cs
│
└── Program.cs
二、代码实现
✅ 1. 自定义验证特性
🔹 RequiredAttribute.cs:
[AttributeUsage(AttributeTargets.Property)]
public class RequiredAttribute : Attribute
{
public string ErrorMessage { get; set; }
public RequiredAttribute(string errorMessage = "该字段是必填项")
{
ErrorMessage = errorMessage;
}
}
🔹 StringLengthAttribute.cs:
[AttributeUsage(AttributeTargets.Property)]
public class StringLengthAttribute : Attribute
{
public int MaxLength { get; set; }
public int MinLength { get; set; }
public string ErrorMessage { get; set; }
public StringLengthAttribute(int minLength = 0, int maxLength = int.MaxValue, string errorMessage = "长度不符合要求")
{
MinLength = minLength;
MaxLength = maxLength;
ErrorMessage = errorMessage;
}
}
✅ 2. 定义实体模型
🔹 User.cs:
using ValidationDemo.Attributes;
public class User
{
[Required("用户名不能为空")]
[StringLength(3, 20, "用户名长度应在3-20之间")]
public string Username { get; set; }
[StringLength(6, 100, "密码必须在6-100字符之间")]
public string Password { get; set; }
[Required("邮箱是必填项")]
public string Email { get; set; }
}
✅ 3. 核心验证器
🔹 ObjectValidator.cs:
using System.Reflection;
using ValidationDemo.Attributes;
public class ObjectValidator
{
public static List<string> Validate(object obj)
{
var errors = new List<string>();
if (obj == null) throw new ArgumentNullException(nameof(obj));
Type type = obj.GetType();
PropertyInfo[] props = type.GetProperties();
foreach (var prop in props)
{
var value = prop.GetValue(obj);
// Required 检查
var requiredAttr = prop.GetCustomAttribute<RequiredAttribute>();
if (requiredAttr != null && (value == null || string.IsNullOrWhiteSpace(value.ToString())))
{
errors.Add($"{prop.Name}: {requiredAttr.ErrorMessage}");
}
// StringLength 检查
var stringLengthAttr = prop.GetCustomAttribute<StringLengthAttribute>();
if (stringLengthAttr != null && value is string strVal)
{
if (strVal.Length < stringLengthAttr.MinLength || strVal.Length > stringLengthAttr.MaxLength)
{
errors.Add($"{prop.Name}: {stringLengthAttr.ErrorMessage}");
}
}
}
return errors;
}
}
✅ 4. 测试入口
🔹 Program.cs:
using ValidationDemo.Models;
using ValidationDemo.Validators;
class Program
{
static void Main()
{
var user = new User
{
Username = "Al",
Password = "123", // 太短
Email = "" // 必填为空
};
var results = ObjectValidator.Validate(user);
if (results.Any())
{
Console.WriteLine("验证失败:");
foreach (var error in results)
Console.WriteLine($" - {error}");
}
else
{
Console.WriteLine("验证通过!");
}
}
}
输出示例
验证失败:
- Username: 用户名长度应在3-20之间
- Password: 密码必须在6-100字符之间
- Email: 邮箱是必填项
技术点说明
| 技术 | 应用 |
|---|---|
| 属性(Property) | 封装数据字段 |
| 特性(Attribute) | 描述属性的校验规则 |
| 反射(Reflection) | 获取属性信息和特性、读取值 |
| 实体模型校验 | 封装成可复用的验证器 |
权威链接
拓展方向推荐
- ✅ 支持更多特性如:
RangeAttribute、RegexAttribute - ✅ 将验证器封装为中间件,集成至 ASP.NET Core 中(表单校验)
- ✅ 属性缓存 + 表达式树以提升性能(避免频繁反射)
更多详细内容请关注其他相关文章!