[Architect] Abp 框架原理解析(4) Validation
本节目录
介绍
Abp中在Application层集成了validation.
直接上代码吧.
DataAnnotations
这是微软提供的一套验证框架,只用引用程序集System.ComponentModel.DataAnnotations.
自带的各种特性标签就不说了,默认在MVC中已集成此验证.
这里说下验证方法:
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指字段代码名.
ICustomValidate
该接口在标准验证结束后调用.
public interface ICustomValidate : IValidate
{
void AddValidationErrors(List<ValidationResult> results);
}
通常会如下操作:
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
该接口并非验证字段,而是在验证完字段,离开验证过滤器前的时候执行.
一般在此接口做初始化或者其他操作.
public interface IShouldNormalize
{
void Normalize();
}
如:
public class CreateTaskInput : IInput, IShouldNormalize
{
public string Name { get; set; }
public void Normalize()
{
Name = DateTime.Now.ToShortDateString() + "-task";
}
}
实现Abp Validation
在Abp中大致会经历这3个接口.
在这里,仿照Abp验证
先定义接口
public interface IInput
{ }
public interface IShouldNormalize
{
void Normalize();
}
public interface ICustomValidate
{
void AddValidationErrors(List<ValidationResult> results);
}
定义Dto
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
public interface ITaskAppService
{
void CreateTask(CreateTaskInput input);
} public class TaskAppService : ITaskAppService
{
public void CreateTask(CreateTaskInput input)
{
Console.WriteLine("进入CreateTask方法:" + input.Name);
}
}
定义拦截器
public class ValidateInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
new MethodInvocationValidator(invocation.Arguments).Validate();
invocation.Proceed();
}
}
验证逻辑
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("有参数异常");
}
//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);
}
}
}
执行
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
[Architect] Abp 框架原理解析(4) Validation的更多相关文章
- [Architect] Abp 框架原理解析(5) UnitOfWork
本节目录 介绍 分析Abp源码 实现UOW 介绍 UOW(全称UnitOfWork)是指工作单元. 在Abp中,工作单元对于仓储和应用服务方法默认开启.并在一次请求中,共享同一个工作单元. 同时在Ab ...
- [Architect] Abp 框架原理解析(3) DynamicFilters
本节目录 介绍 定义Filter 设置Filter 这是Abp中多租户.软删除.激活\禁用等如此方便的原因 Install-Package EntityFramework.DynamicFilters ...
- [Architect] Abp 框架原理解析(2) EventBus
本节目录 原理介绍 Abp源码分析 代码实现 原理介绍 事件总线大致原理: (1) 在事件总线内部维护着一个事件与事件处理程序相映射的字典. (2) 利用反射,事件总线会将实现 ...
- [Architect] Abp 框架原理解析(1) Module
本节目录 Abp介绍 Abp源码分析 代码实现 Abp介绍 学习了一段时间的Abp,领略了一下前辈的架构.总结还是SOLID,降低耦合性. 虽然从架构上说甚至不依赖于DI框架,但实际上在基础框架中还是 ...
- [Architect] ABP(现代ASP.NET样板开发框架) 翻译
所有翻译文档,将上传word文档至GitHub 本节目录: 简介 代码示例 支持的功能 GitHub 简介 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目) ...
- ABP架构解析
ABP总体介绍 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- [置顶]
滴滴插件化VirtualAPK框架原理解析(二)之Service 管理
在前一篇博客滴滴插件化框架VirtualAPK原理解析(一)之插件Activity管理 中VirtualAPK是如何对Activity进行管理的,本篇博客,我们继续来学习这个框架,这次我们学习的是如何 ...
- ADB运行框架原理解析【转】
本文转载自:http://blog.csdn.net/wlwl0071986/article/details/50935496 一.adb守护进程的初始化 源码路径:~/system/core/adb ...
- Java并发Fork-Join框架原理解析
1.什么是Foirk/Join框架 Fork/Join框架是Java7提供用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 2.什么是并行流与顺 ...
随机推荐
- c#连接SFTP上传文件
名词解释(百度百科) sftp是Secure File Transfer Protocol的缩写,安全文件传送协议.可以为传输文件提供一种安全的加密方法.sftp 与 ftp 有着几乎一样的语法和功能 ...
- [C] zlstdint(让VC、TC等编译器自动兼容C99的整数类型)V1.0。支持Turbo C++ 3等DOS下的编译器
作者:zyl910 以前我曾为了让VC++等编译器支持C99的整数类型,便编写了c99int库来智能处理(http://www.cnblogs.com/zyl910/p/c99int_v102.htm ...
- Chrome谷歌浏览器首页被改为Hao123导航怎么办|附各类解决方法【转】
软件小子:昨天偶然间发现自己的chrome浏览器的首页被篡改成hao123导航了,要是自己设置的还无所谓,但是后面还有尾巴.顿时就火了,又是哪款软件这么流氓,太无良了,我非常确定我肯定是没有勾选什么设 ...
- python 中偏函数 partial 的使用
函数的partial应用 函数在执行时,要带上所有必要的参数进行调用.但是,有时参数可以在函数被调用之前提前获知.这种情况下,一个函数有一个或多个参数预先就能用上,以便函数能用更少的参数进行调用. 例 ...
- Django 源码小剖: 更高效的 URL 调度器(URL dispatcher)
效率问题 django 内部的 url 调度机制说白了就是给一张有关匹配信息的表, 这张表中有着 url -> action 的映射, 当请求到来的时候, 一个一个(遍历)去匹配. 中, 则调用 ...
- Discuz!开发手册
如何使用Discuz开发手册? 1.首先建议你了解Discuz目录结构-全局篇 通过对目录结构的了解,会在以后的创作道路上提供坚实的基础! 2.你还需要了解Discuz! X3.1数据字典 3.创建自 ...
- SVN的文件夹链接(目录链接,目录映射,svn:externals)
首先大家可以看下SVN的文件夹链接太强大了!(目录链接,目录映射,svn:externals),我就是看了这篇文章才敢大刀阔斧的把项目里的外链修改成正确的链接. 问题: 我们的项目里,服务器脚本工程s ...
- Python的Descriptor和Property混用
一句话,把Property和Descriptor作用在同一个名字上,就只有Property好使.
- Swift之手势总结
手势个人笔记,代码简单,不过多赘述. 建立手势只需三步 建立和设置手势识别器实例,设置target,action,指定一些属性 附加识别器到视图 实现action方法 1.首先还是创建一个view @ ...
- 少睡与吸烟影响IQ
导读:据英国<每日邮报>报道,根据科学家一项最新研究发现,一晚的糟糕睡眠,对大脑可能产生很大损害,就等同头部遭到了一次严重的撞击.长期睡眠不好会造成智力下降,请看[科学探索]揭秘: ...