本节目录

介绍

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的更多相关文章

  1. [Architect] Abp 框架原理解析(5) UnitOfWork

    本节目录 介绍 分析Abp源码 实现UOW 介绍 UOW(全称UnitOfWork)是指工作单元. 在Abp中,工作单元对于仓储和应用服务方法默认开启.并在一次请求中,共享同一个工作单元. 同时在Ab ...

  2. [Architect] Abp 框架原理解析(3) DynamicFilters

    本节目录 介绍 定义Filter 设置Filter 这是Abp中多租户.软删除.激活\禁用等如此方便的原因 Install-Package EntityFramework.DynamicFilters ...

  3. [Architect] Abp 框架原理解析(2) EventBus

    本节目录 原理介绍 Abp源码分析 代码实现 原理介绍 事件总线大致原理: (1)       在事件总线内部维护着一个事件与事件处理程序相映射的字典. (2)       利用反射,事件总线会将实现 ...

  4. [Architect] Abp 框架原理解析(1) Module

    本节目录 Abp介绍 Abp源码分析 代码实现 Abp介绍 学习了一段时间的Abp,领略了一下前辈的架构.总结还是SOLID,降低耦合性. 虽然从架构上说甚至不依赖于DI框架,但实际上在基础框架中还是 ...

  5. [Architect] ABP(现代ASP.NET样板开发框架) 翻译

    所有翻译文档,将上传word文档至GitHub 本节目录: 简介 代码示例 支持的功能 GitHub 简介 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目) ...

  6. ABP架构解析

    ABP总体介绍 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...

  7. [置顶] 滴滴插件化VirtualAPK框架原理解析(二)之Service 管理

    在前一篇博客滴滴插件化框架VirtualAPK原理解析(一)之插件Activity管理 中VirtualAPK是如何对Activity进行管理的,本篇博客,我们继续来学习这个框架,这次我们学习的是如何 ...

  8. ADB运行框架原理解析【转】

    本文转载自:http://blog.csdn.net/wlwl0071986/article/details/50935496 一.adb守护进程的初始化 源码路径:~/system/core/adb ...

  9. Java并发Fork-Join框架原理解析

    1.什么是Foirk/Join框架 Fork/Join框架是Java7提供用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 2.什么是并行流与顺 ...

随机推荐

  1. Python 目录操作

    知道两个文件的绝对目录,怎样计算出两个文件的相对目录,例如:知道 a = '/usr/share/pyshared/test/a.py' b = '/usr/lib/dist/test/a.py' 可 ...

  2. php中如何创建文件夹

    这个功能比较简单,直接上代码了: $dir = iconv("UTF-8", "GBK", "Public/bookcover"); if ...

  3. HTTP 错误 500.21 - Internal Server Error 处理程序“ExtensionlessUrlHandler-ISAPI-4.0_64bit”在其模块列表中有一个错误模块“IsapiModule” 解决方法

    IIS在发布网站后找不到首页,提示以上错误,原因是在“应用程序池”中,把对应的网站的“托管管道模式”设置为“集成”即可.

  4. Codeforces Round #182 (Div. 1)题解【ABCD】

    Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...

  5. nodejs 的安全

    1.connect中间件csrf 原理:在express框架中csrf 是通过connect 模块的中间件来解决的.其原理是在前端构造一个隐藏的表单域“_csrf” ,后端生成一个值,作为该表单域,然 ...

  6. WPF 设置程序开机自动运行(+注册表项)

    #region 设置程序开机自动运行(+注册表项) RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Micr ...

  7. 10大经典CSS3菜单应用欣赏

    很多时候,我们的网页菜单需要个性化,从而来适应各种行业的用户视觉操作体验.本文将带领大家一起来欣赏10个非常经典的CSS3菜单应用,菜单涉及到动画菜单.Tab菜单.面包屑菜单等. 1.CSS3飘带状3 ...

  8. 编写并发程序 Inversion

    做完了 scala parallel 课程作业后,觉得 scala 写并发程序的便捷性是 java 永远都追不上的.scala 的Future 和 Promise,java 里 Future 和 Co ...

  9. [转]C++学习–基础篇(书籍推荐及分享)

    C++入门 语言技巧,性能优化 底层硬货 STL Boost 设计模式 算法篇 算起来,用C++已经有七八年时间,也有点可以分享的东西: 以下推荐的书籍大多有电子版.对于技术类书籍,电子版并不会带来一 ...

  10. FileZilla FTP Server 高级防火墙例外

    在防火墙中: 在“例外”中,添加端口21,TCP 添加端口50000,TCP (或添加一组端口,一个一个的也行,如果你在软件中选择的是50000-51000,而在这里只打开了50000的单个端口,登录 ...