[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.什么是并行流与顺 ...
随机推荐
- iOS 同一设备内的应用之间资源共享的实现
我们都知道,iOS为安全考虑,各应用只能使用其自已的应用沙盒内的存储空间,各应用之间是不能互相访问彼此的沙盒空间的. 另外,iOS设备都没有外置存储卡,这样,象 Android 设备间共同访问外置存储 ...
- Mac OS 中设置VPN(pptp连接方式)
第一步:点击系统设置(如图) 第二步:点击网络,进入网络设置(如图) 第三步:点击+号-创建新服务,创建新的VPN网络连接(如图) 第四步:接口-中选-VPN, VPN类型-中选-PPTP,服务名称- ...
- NuGet学习笔记(转)
NuGet学习笔记(1)——初识NuGet及快速安装使用 http://kb.cnblogs.com/page/143190/ 1. NuGet是什么? NuGet is a Visual Studi ...
- Codeforces Round #379 (Div. 2) C. Anton and Making Potions 枚举+二分
C. Anton and Making Potions 题目连接: http://codeforces.com/contest/734/problem/C Description Anton is p ...
- 每日英语:A New Way to Learn Chinese
Entrepreneur and author ShaoLan Hsueh thinks that English-speakers can start learning to read Chines ...
- gem install 出现Errno::ECONNRESET: Connection reset by peer - SSL_connect (https://api.rubygems.org
在安装了rvm来管理多版本的ruby之后,想在不同环境下安装一些gems,结果gem install puma 之后,发现一次又一次失败. gem install 出现Errno::ECONNRESE ...
- 单源最短路径算法---Dijkstra
Dijkstra算法树解决有向图G=(V,E)上带权的单源最短路径问题,但是要求所有边的权值非负. 解题思路: V表示有向图的所有顶点集合,S表示那么一些顶点结合,从源点s到该集合中的顶点的最终最短路 ...
- iOS开发问题之Could not instantiate class named NSLayoutConstraint
这个问题在ios6.0之前的版本中运行会出现,因为使用Xcode 4.5之后的版本新建项目默认是选中AutoLayout的,但这个特性是在iOS6.0之后的版本中才支持的. 解决办法是选中.stroy ...
- JS实现移动端图片延迟加载
图片延迟加载常见的有,jquery.lazyload.js,原生JS实现的echo.js.但是都是必须给图片设置宽高. 因为项目是移动端,而且无法在加载前知道图片的宽高,所以,只好自己写了一个. 既然 ...
- JMir——Java版热血传奇2之资源文件与地图
我虽然是90后,但是也很喜欢热血传奇2(以下简称“传奇”)这款游戏. 进入程序员行业后自己也对传奇客户端实现有所研究,现在将我的一些研究结果展示出来,如果大家有兴趣的话不妨与我交流. 项目我托管到co ...