[Architect] Abp 框架原理解析(4) Validation
本节目录
介绍
Abp中在Application层集成了validation.
直接上代码吧.
DataAnnotations
这是微软提供的一套验证框架,只用引用程序集System.ComponentModel.DataAnnotations.
自带的各种特性标签就不说了,默认在MVC中已集成此验证.
这里说下验证方法:
1 2 3 4 5 6 7 | static void Main( string [] args) { var obj = new object (); var rst = new StringLengthAttribute(10) { MinimumLength = 6 }.GetValidationResult( "Never" , new ValidationContext(obj) { DisplayName = "名称" , MemberName = "Name" }); Console.WriteLine(rst); Console.ReadKey(); } |
运行结果:
ValidationResult对象
在MVC中,obj指的是验证的对象,DisplayName指DisplayName特性的Name值,Member指字段代码名.
1 |
ICustomValidate
该接口在标准验证结束后调用.
1 2 3 4 | public interface ICustomValidate : IValidate { void AddValidationErrors(List<ValidationResult> results); } |
通常会如下操作:
1 2 3 4 5 6 7 8 9 10 11 | public class CreateTaskInput : IInput, ICustomValidate { public string Name { get ; set ; } public void AddValidationErrors(List<ValidationResult> results) { if (Name == "xx" ) { results.Add( new ValidationResult( "Task 名非法" )); } } } |
当标准验证功能无法完成某些特定的验证功能,可以使用此接口.
IShouldNormalize
该接口并非验证字段,而是在验证完字段,离开验证过滤器前的时候执行.
一般在此接口做初始化或者其他操作.
1 2 3 4 | public interface IShouldNormalize { void Normalize(); } |
如:
1 2 3 4 5 6 7 8 | public class CreateTaskInput : IInput, IShouldNormalize { public string Name { get ; set ; } public void Normalize() { Name = DateTime.Now.ToShortDateString() + "-task" ; } } |
实现Abp Validation
在Abp中大致会经历这3个接口.
在这里,仿照Abp验证
先定义接口
1 2 3 4 5 6 7 8 9 10 11 12 | public interface IInput { } public interface IShouldNormalize { void Normalize(); } public interface ICustomValidate { void AddValidationErrors(List<ValidationResult> results); } |
定义Dto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class CreateTaskInput : IInput, IShouldNormalize, ICustomValidate { [StringLength(10, MinimumLength = 5)] public string Name { get ; set ; } public void Normalize() { Name = DateTime.Now.ToShortDateString() + "-task" ; } public void AddValidationErrors(List<ValidationResult> results) { if (Name == "xx" ) { results.Add( new ValidationResult( "Task 名非法" )); } } } |
定义ApplicationService
1 2 3 4 5 6 7 8 9 10 11 12 | public interface ITaskAppService { void CreateTask(CreateTaskInput input); } public class TaskAppService : ITaskAppService { public void CreateTask(CreateTaskInput input) { Console.WriteLine( "进入CreateTask方法:" + input.Name); } } |
定义拦截器
1 2 3 4 5 6 7 8 | public class ValidateInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { new MethodInvocationValidator(invocation.Arguments).Validate(); invocation.Proceed(); } } |
验证逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | internal class MethodInvocationValidator { private readonly object [] _parameterValues; private readonly List<ValidationResult> _validationErrors; /// <summary> /// Creates a new <see cref="MethodInvocationValidator"/> instance. /// </summary> /// <param name="parameterValues">List of arguments those are used to call the <paramref name="method"/>.</param> public MethodInvocationValidator( object [] parameterValues) { _parameterValues = parameterValues; _validationErrors = new List<ValidationResult>(); } public void Validate() { //basic validate for ( var i = 0; i < _parameterValues.Length; i++) { ValidateObjectRecursively(_parameterValues[i]); } //throw exception if (_validationErrors.Any()) { foreach ( var validationResult in _validationErrors) { Console.WriteLine( "{0}:{1}" , validationResult.MemberNames.FirstOrDefault(), validationResult.ErrorMessage); } throw new Exception( "有参数异常" ); }<br> //normalize foreach ( var parameterValue in _parameterValues) { if (parameterValue is IShouldNormalize) { (parameterValue as IShouldNormalize).Normalize(); } } } private void ValidateObjectRecursively( object validatingObject) { var properties = TypeDescriptor.GetProperties(validatingObject).Cast<PropertyDescriptor>(); foreach ( var property in properties) { var validationAttributes = property.Attributes.OfType<ValidationAttribute>().ToArray(); if (validationAttributes.IsNullOrEmpty()) { continue ; } var validationContext = new ValidationContext(validatingObject) { DisplayName = property.Name, MemberName = property.Name }; foreach ( var attribute in validationAttributes) { var result = attribute.GetValidationResult(property.GetValue(validatingObject), validationContext); if (result != null ) { _validationErrors.Add(result); } } } //custom validate if (validatingObject is ICustomValidate) { (validatingObject as ICustomValidate).AddValidationErrors(_validationErrors); } } } |
执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | static void Main( string [] args) { using ( var container = new WindsorContainer()) { container.Register(Component.For<IInterceptor, ValidateInterceptor>()); //先注入拦截器 container.Kernel.ComponentRegistered += Kernel_ComponentRegistered; container.Register(Component.For<ITaskAppService, TaskAppService>()); var person = container.Resolve<ITaskAppService>(); person.CreateTask( new CreateTaskInput() { Name = "123" }); } Console.ReadKey(); } static void Kernel_ComponentRegistered( string key, Castle.MicroKernel.IHandler handler) { handler.ComponentModel.Interceptors.Add( new InterceptorReference( typeof (ValidateInterceptor))); } |
将name改成"12345"
本文地址:http://neverc.cnblogs.com/p/5267425.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义