首页 > 代码库 > Attribute特性验证模型model

Attribute特性验证模型model

数据验证我们往往分为前台验证和后台验证,而我们的后台验证每到一个方法中就要去验证一次,这样的代码想想都难以维护,这篇我们这篇文章就是为了解决这样的问题。用attribute 这个特性来解决这样的问题

也将在这篇文章中告诉大家如何编写。

调用方式:

  UserService applictionService = container.Resolve<UserService>();
            applictionService.AddUser(new User() { Name = "1",Age="bu gai " });
           
            Console.ReadLine();

User 类:

    public class User
    {
        [StringLength(2,10)]
        public string Name { get; set; }
        [StringLength(5,10)]
        public string Age { get; set; }
    }

结果:

技术分享

 

 

要做到上面的效果,笔者用的技术有:

1.Castle 的依赖注入

2.Castle 的动态代理技术

3.Attribute特性的了解

4.反射技术

 

 如果上面的技术你还不了解得话,你可以借助百度进行自行脑补

 

在介绍细节之前,我们先来看看笔者的一个目录结构,然后在介绍每个类的细节

技术分享

 

1.ServiceInstaller:是这个test项目的核心依赖注入类

2.User :是测试model

3.IApplicationService:是服务的接口,在这里你们可以理解成mvc控制器接口

4.OrderService,UserService是两个实现类,

5.ServiceInterceptor:是动态代理类,也是实现这个功能的核心

6.MethodInvocationValidator:是在方法执行之前进行实体model的验证

7.ValidateAttribute:是验证的基类

8.StringLength:是特性字符串长度的验证

 

上面的有些类我就不一一进行讲解,主要讲解的就是ServiceInstaller,MethodInvocationValidator,ServerInterceptor

 

ServiceInstaller代码:

 public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Component.For<IWindsorContainer>().Instance(container).LifestyleSingleton());

            container.Register(Classes.FromThisAssembly().BasedOn<IApplicationService>().WithService.DefaultInterfaces());

            container.Register(Classes.FromThisAssembly().BasedOn<IInterceptor>().WithService.DefaultInterfaces());

            container.Register(Component.For<MethodInvocationValidator>().LifestyleTransient());

        }

  public static void Init(IWindsorContainer container)
        {
            container.Kernel.ComponentRegistered += Kernel_ComponentRegistered;
        }

        private static void Kernel_ComponentRegistered(string key, Castle.MicroKernel.IHandler handler)
        {
            if (typeof(IApplicationService).IsAssignableFrom(handler.ComponentModel.Implementation))
            {
                handler.ComponentModel.Interceptors.Add(new Castle.Core.InterceptorReference(typeof(ServiceInterceptor.ServiceInterceptor)));
            }
        }

第一注入就是对IWindsorContainer 自身的一个注入,因为其他要用到它,它是一个单例模式的。

 

对也剩下的我想大家都懂,就是对这个应用程序集,继承自IApplicationService,IInterceptor的实体类进行注入,container.Kernel.ComponentRegistered是每注入一个组件就是执行这个事件,当我们注册的组件中继承了IApplication的实体类进行动态代理注入,

 

ServerInterceptor 代码:

 public class ServiceInterceptor : IInterceptor
    {
        private readonly IWindsorContainer _container;
        public ServiceInterceptor(IWindsorContainer contaier)
        {
            _container = contaier;
        }
        public void Intercept(IInvocation invocation)
        {
            try
            {
                var methodValidator = _container.Resolve<MethodInvocationValidator>();
                methodValidator.Initialize(invocation.Method, invocation.Arguments);
                methodValidator.Validator();
                invocation.Proceed();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
           
        }
    }

 这个类就是每当调用service实体类时的方法时,就会触发这个Intercept方法, invovation参数包含了方法的信息和方法的参数数据,为我们反射提供基础

MethodInvocationValidator 代码:

 //验证属性是否通过
        public void Validator()
        {
            for (int i=0;i<Method.GetParameters().Length;i++)
            {
                var paraInfo = Method.GetParameters()[i];
                foreach (PropertyInfo proInfo in  paraInfo.ParameterType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
                {
                    foreach (CustomAttributeData attr in proInfo.CustomAttributes)
                    {
                       
                      var df= (ValidateAttribute) Activator.CreateInstance(attr.AttributeType, GetConstructorArguments(attr.ConstructorArguments));
                        var result= df.IsValidate(proInfo.GetValue(ParameterValues[i]));
                        if (!result)
                        {
                            ValidationErrors.Add(df.FormatMsgs(proInfo.Name));
                        }

                    }
                }
                if (ValidationErrors.Count > 0)
                {
                    throw new Exception(ValidationErrors[0]);
                }
            }
        }

这个主要对调用方法的的参数进行反射,如果验证通过则调用原本的方法,不通过在一个新的异常,在外面捕获,并打印出来,

 

最后:如果有什么不懂地方欢迎留言,dome链接 http://files.cnblogs.com/files/xuehaiyiye/TestNanHua.zip

Attribute特性验证模型model