[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.什么是并行流与顺 ...
随机推荐
- Windows搭建SVN
1.服务器下载 VisualSVN 地址:http://subversion.apache.org/packages.html 2.然后下载TortoiseSVN客户端,如果要下中文语言包 也在这个页 ...
- 手机前端页面js
(function () { var phoneWidth = parseInt(window.screen.width); var phoneScale = phoneWidth / 640; va ...
- OGG-03517 Conversion from character set failed解决方法
用goldengate同步oracle数据到mysql,由于一个字段某行数据的字段集的原因导致 replicat进程报 OGG-03517错 OGG-03517 Conversion from ch ...
- 4M宽带一般最大的下载速度是多少?
4M宽带理论速度=4Mbit/s=4096 Kbit/s=512 KByte/s宽带速度其实是有两个参数的:上行(上传速度).下行(下载速度),一般宽带标为4M其实是说下载速度是4M(即512KB/每 ...
- LR6 碱性电池才能带动微软鼠标
LR6 碱性电池才能带动微软鼠标 好前一段买个一个微软无线鼠标后来动弹不得,更换电池也不行,本来lp说为什么不扔掉,但因为实在做得很漂亮一直带在身边.改用雷柏的普通无线鼠标后也很是好用.不过要经常 ...
- 【网络——Linux】——IPMI详细介绍【转】
一.IPMI含义 智能平台管理接口(IPMI:Intelligent Platform Management Interface)是一项应用于服务器管理系统设计的标准,由Intel.HP.Dell和N ...
- C#判断一个string是否为数字
案一:Try...Catch(执行效率不高) private bool IsNumberic(string oText) { try { int var1=Convert.ToInt32 (oText ...
- ubuntu-15.04-server-i386.iso 安装 Oracle 11gR2 数据库
特点: 需要重新安装老版本的 libaio1_0.3.109-2ubuntu?_i386.deb.默认的libaio库有问题,和其默认libaio的编译方式有关! 默认的gcc 4.9 需要使用 -W ...
- Show Linux Package Sort By Size
ArchLinux: ~ $ pacsysclean Debian: ~ $ sudo apt-get install debian-goodies ~ $ dpigs -H
- Schema Workbench 开发mdx和模式文件
一.前言 安装了saiku之后,每次修改schema文件,非常耗时,每次都要经历若干步骤:修改xml.上传.重启才能生效,并且非常不利于学习和理解MDX和模式文件,踌躇之际,发现了这个工具,十分小巧方 ...