• [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

  • 相关阅读:
    C# RabbitMQ
    使用HttpClient和WebRequest时POST一个对象的写法
    HTTP中application/x-www-form-urlencoded字符说明
    MVC5 Entity Framework学习
    SQL Server安全
    Entity Framework查询
    COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 80070005 拒绝访问。最新解决方案
    js中精度问题以及解决方案
    string.format
    t-sql对被除数为0&除数小于被除数结果为0&除法保留2位小数的处理
  • 原文地址:https://www.cnblogs.com/neverc/p/5267425.html
Copyright © 2020-2023  润新知