数据验证我们往往分为前台验证和后台验证,而我们的后台验证每到一个方法中就要去验证一次,这样的代码想想都难以维护,这篇我们这篇文章就是为了解决这样的问题。用attribute 这个特性来解决这样的问题
也将在这篇文章中告诉大家如何编写。
调用方式:
UserService applictionService = container.Resolve<UserService>();
applictionService.AddUser(new User() { Name = "",Age="bu gai " }); Console.ReadLine();
User 类:
public class User
{
[StringLength(,)]
public string Name { get; set; }
[StringLength(,)]
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=;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 > )
{
throw new Exception(ValidationErrors[]);
}
}
}
这个主要对调用方法的的参数进行反射,如果验证通过则调用原本的方法,不通过在一个新的异常,在外面捕获,并打印出来,
最后:如果有什么不懂地方欢迎留言,dome链接 http://files.cnblogs.com/files/xuehaiyiye/TestNanHua.zip