ModelValidator基于元数据的验证
modelvalidator主要是应用在modelmetadata元数据的类型上或类型属性上。它是验证的基础类型,所有的modelvalidatorproviders、dataannotationvalidator、dataannotationvalidatorprovider都是主要通过getvalidators这个方法来获取ienumerable<modelvalidator>对象。然后循环这个迭代对象,利用modelvalidator的validator对每个元数据进行验证。有个例子可以很好的说明:
1 private ienumerable<modelvalidator> getvalidator(type type) 2 { 3 modelvalidatorprovider provider=new dataannodationmodelvalidatorprovider();
modelmetadata metadata=modelmetadataproviders.current.getmetadatafortype(null,type);
foreach(var validator in provider.getvalidator(metadata,controllercontext))
{
yeild return validator
}
foreach(var propertymetadata in metadata.properties)
{
foreach(var validator in provider.getvalidator(propertymetadata,controllercontext))
yeild return validator;
}
4 }
元数据modelmetadata包含:ienumrable<modelvalidator> getvalidator(contollercontext) 实现方法:
ienumrable<modelvalidator> getvalidator(controllercontext context) { return modelvalidatorproviders.providers.getvalidator(this,context) }
其中providers来源:
private static readonly modelvalidatorprovidercollection _providers=new modelvalidatorprovidercollecton
{
new dataannotationmodelvalidatorprovider(),
new dataerrorinfomodelvalidatorprovider(),
new clinetdatatypemodelvalidatorprovider()
}
继续实现 providets的getvalidator的方法:
public class modelvalidatorprovidercollection:icollection<modelvalidatorprovider>
{
public ienumrable<modelvalidator> getvalidator(modelmedatata modeltadata,controllercontext context)
{
return this.combinditems.selectmany(modelvalidatorprovider provider)=>provider.getvalidators(modeltadata,context);
//这个方法combinditems可理解为内部已定义数据集合和外部自定义的数据集合的合计。具体的实现在multiserviceresolver:iresolver<ienumrable<tserverice>>中
}
//对了这个类我本来不想往下记录下 但是为了以后再学习和本着研究的心态还是硬着头皮写写去吧
public iresolver<ienumrable<modelvalidatorprovider>> _serviceresolver;
privite ienumeable<modelvalidator> combinditems
{
get{
return this._serviceresoler.current;
}
}
public modelvalidatorprovidercollection()
{
this._serviceresolver=new multiserviceresolver<modelvalidatorprovider>(()=>this.items);
}
public modelvalidatorprovidercollection(ilist<modelvalidatorprovider> list):base(list);
{
this._serviceresolver=new multiserverresolver<modelvaldatorprovider>(()=>this.items);
}
internal modelvalidatorprovidercollection(ireslover<ienumrable<modelvalidatorprovider>> services,params modelvalidatorprovider[] modelvalidatorproviders):base(modelvalidatorproviders)
{
iresolver<ienumrable<modelvalidaotprovider>> arge=services;
if(arge==null)
{
arge=new multiservicereslover<modelvalidatorprovider>(this.items);
}
this._serviceresolber=arge;
}
prottect override void setitem(int index,modelvalidatorprovider item)
{
if(item==null)
throw new argumentnullexception("item");
base.setitem(index,item);
}
}
//【下面要介绍的是multiserviceresolver类的只要实现,主要是通过依赖组件dependencyresolver.current的gerservices<tservice>得到一组数据,然后通过构造函数传入的委托方法得到另外一组数据,通过current实现两组数据的结合】
public class multiservicereslover<tservice>:iservice<ienumrable<tservice>> where tservice :class
{
private lazy<ienumerable<tservice>> _itemsformservice;
private func<ienumrable<iservice>> _itemthunk;
private func<ienumrable<tservice>> _resolverthunk;
public ienumrable<tservice> current
{
get{
return this.itemsformservice.value.cacat(this._itemthunk());
}
}
public multiserviceresolve(func<ienumrable<tservice>> itemsthunk)
{
if(itemthunk==null)
throw new argumentnullexception("itemthunk");
this._itemsthunk=itemsthunk;
this._resolverthunk=(()=>dependencyresolver.curremt);
this._itemsformservices=new lazy<ienumerable<tservice>>(()=>this._resolverthunk.getservice<tservice>());
}
}
前面一直围绕着获取modelvalidatorprovider来实现方法。可modelvalidatorprovider本身是一个抽象类和只有一个abstract的getvalidators(modelmedata,controllercontext)的方法。现在对系统中默认继承和实现modelvalidatorprovider抽象类的其中一个比较常用的类型做说明,那就是 dataannotationmodelvalidatorprovider,它是系统间接实现了modelvalidatorprovider,是我们最常用的基于验证特性的声明式 model 验证。
在了解dataannotationmodelvalidatorprovider时 会提到dataannotationmodelvalidator这类,它具体地实现了modelvalidator定义的方法(包括validate(object container))。
public class dataannotationmodelvalidatorprovider:associtatedvalidatorprovider { //这里只编辑主要的实现方法 // 这里的dataannotationmodelvalidatorfactory的系统定义的一个委托。如果元数据属性未定义在attributefactories中 则采用默认的modelvalidator对象 internal static dataannotationmodelvalidatorfactory defaultattributefactory=(modelmetadata metadata,controllercontext context,validatorattribute attrubute)=>new dataannotaionmodelvalidator(metadata,context,attribute); //主要为创建元数据"自我验证"集合,可以通过registervalidatableobjectadapter(type modeltype,type adaptertype)来实现自我注册 internal static dictionary<type,dataannotationmodelvalidatorfactiory> attributefactories=dataannotationmodelvalidatorprovider.buildattributefactoriesdictionary(); //接下来是最主要的代码了 protext override ienumerable<modelvalidator> getvalidators(modelmetadata metadata,controllercontext context,validatorattribute attributes) { var result=new list<modelvalidator>; try{ //这一步的意思是: addimplicitrequiredattributeforvaluetypes (为值类型添加隐式必填验证) 值为true,元数据也声明了required=true,则必须在attributes里包含 requiredattribute if(dataannotatoonmodelvalidatorprovider.addimplicitrequiredattributeforvaluetype && metadata.isrequired) { if(!attributes.any((attribute t)=>t is requiredattribute)) { attrubutes=attribites.concat(new requiredattribute[]{new requiredattrbute()}); } } foreach(var validatorattribute current in attributes.oftype<validatorattribute>) { dataannotationmodelvalidatorfactory defaultfactory; if(!dataannotationmodelvalidatorprovider.attrbutefactories.tryvalue(current.gettype(),out defualtfactory)) { defaultfactory=dataannotationmodelvalidatorprovider.defaultattrbutefactoty; } result.add(defaultfactory(metadata,context,current)) } if(typeof(ivalidatableobject).isassignableform(medatat.modeltype)) { dataannotationsvalidatableobjectadapterfactory defaultvalidatablefactory; if (!dataannotationsmodelvalidatorprovider.validatablefactories.trygetvalue(metadata.modeltype, out defaultvalidatablefactory)) { defaultvalidatablefactory = dataannotationsmodelvalidatorprovider.defaultvalidatablefactory; } result.add(defaultvalidatablefactory(metadata, context)); } } finally{ } return result; } //上面这个方法写了这么多无非就是 根据元数据上的属性获取继承了modelvalidator的对象集合,然后利用集合里每个对象所定义的validator方法进行验证 //下面是一些自定义注册方法 public static void registadapter(type attrbutetype,type adapertype) { //获取当前 adapertype的特定构造函数 constructorinfo constructor=adaptertype.getconstructor(typeof(modelmetadata),typeof(controllercontext),attrbutetype); try{ dataannotationmodelvalidatorprovider.attributefacties[attrbutetype]=((modelmedatada metadata,controllercontext context,validatorattribute attribute)=>(modelvalidator)constructor.invoker(new object[]{metadata,context,attrbute})); } finally{ } } //直接用委托方法注册 public static void registeradapterfactory(type attributetype,dataannotationsmodelvalidatorfactory factory) buildattributefacoriesdictionary { //还有好多自定义注册方法 反编译后查看吧 //下面实现的是系统自定义一些validatorattribute private static dictionary<type,dataannotationmodelvalidatorfactory> dictionary=new dictionary<type,dataannotationmodelvalidatorfactory>(); dataannotationsmodelvalidatorprovider.addvalidationattributeadapter(dictionary, typeof(rangeattribute), (modelmetadata metadata, controllercontext context, validationattribute attribute) => new rangeattributeadapter(metadata, context, (rangeattribute)attribute)); dataannotationsmodelvalidatorprovider.addvalidationattributeadapter(dictionary, typeof(regularexpressionattribute), (modelmetadata metadata, controllercontext context, validationattribute attribute) => new regularexpressionattributeadapter(metadata, context, (regularexpressionattribute)attribute)); dataannotationsmodelvalidatorprovider.addvalidationattributeadapter(dictionary, typeof(requiredattribute), (modelmetadata metadata, controllercontext context, validationattribute attribute) => new requiredattributeadapter(metadata, context, (requiredattribute)attribute)); dataannotationsmodelvalidatorprovider.addvalidationattributeadapter(dictionary, typeof(stringlengthattribute), (modelmetadata metadata, controllercontext context, validationattribute attribute) => new stringlengthattributeadapter(metadata, context, (stringlengthattribute)attribute)); dataannotationsmodelvalidatorprovider.addvalidationattributeadapter(dictionary, validationattributehelpers.membershippasswordattributetype, (modelmetadata metadata, controllercontext context, validationattribute attribute) => new membershippasswordattributeadapter(metadata, context, attribute)); dataannotationsmodelvalidatorprovider.addvalidationattributeadapter(dictionary, validationattributehelpers.compareattributetype, (modelmetadata metadata, controllercontext context, validationattribute attribute) => new compareattributeadapter(metadata, context, attribute)); dataannotationsmodelvalidatorprovider.addvalidationattributeadapter(dictionary, validationattributehelpers.fileextensionsattributetype, (modelmetadata metadata, controllercontext context, validationattribute attribute) => new fileextensionsattributeadapter(metadata, context, attribute)); dataannotationsmodelvalidatorprovider.adddatatypeattributeadapter(dictionary, validationattributehelpers.creditcardattributetype, "creditcard"); dataannotationsmodelvalidatorprovider.adddatatypeattributeadapter(dictionary, validationattributehelpers.emailaddressattributetype, "email"); dataannotationsmodelvalidatorprovider.adddatatypeattributeadapter(dictionary, validationattributehelpers.phoneattributetype, "phone"); dataannotationsmodelvalidatorprovider.adddatatypeattributeadapter(dictionary, validationattributehelpers.urlattributetype, "url"); return dictionary; } }
上面这个类引用了之类associatedvalidatorprovider associated(关联的意思)。这个类首先利用getvalidator(modelmetadata,controllercontext) 对元数据提取attribute, 得到的attribute数组去调用抽象方法getvalidator(modelmetadata,controllercontext,ienumrable<modelvalidator>),这个方法在上面的dataannotationmodelvalidatorprovider被实现。
associatedvalidatorprovider类重点对传入的元数据modelmetadata进行解析。
public sealed override ienumerable<modelvalidator> getvalidators(modelmetadata metadata,controllercontext context) { if(metadata==null) throw new argumentnullexecption("metadata"); if(context==null) throw new argumentnullexecption("context"); } protect abstract ienumrable<modelvalidator> getvalidators(modelmetadata,controllercontext,ieunmerable<attribute> atttibutes);//这个抽象方法在上面类(dataannotationmodelvalidatorprovider)里有具体的实现 protected override icustomtypedescriptor gettypedescriptor(type type) { return typedescriptorhepler.get(type); } pritvate ienumerable<modelvalidator> getvalidatorforproperty(modelmetadata metadata,controllercontextg context) { icustomtypedescriptor typedescriptor=this.gettypedescriptor(metadata.containertype); propertydescriptor propertydescriptor=typedescriptor.getproperties.find(metadata.propertyname,true); if(propertydescriptor==null) throw new argumentexception("propertynofound"); return this.getvalidator(metadata,context,propertydescriptor.attributes.oftype<attribute>); } private ienumerable<modelvalidator> getvalidatorsfortype(medelmetadata metadata,controllercontext context) { return this.getvalidator(metadata,context,this.gettypedescriptor(metadata.modeltype).getattributes().cast<attribue>); }
上面的dataannotationmodelvalidatorprovider中 根据属性来查找实现委托dataannotationsmodelvalidationfactory时,有一个默认的实现:dataannotationsmodelvalidator。这个方法是真正实现了验证功能validate(object contatiner).
下面就是这个类大概的实现过程。
public class dataannotationmodelvalidator:modelvalidator { public override ienumerable<modelvalidatorresult> validate(object container) { validationcontext validationcontext=new validationcontext(container??base.metadata.model,null,null); validationcontext.displayname=this.metadata.displayname(); validationresult result=this.attribute.getvalidationresult(base.metadata.model,validationcontext); if(result!=result.scuess) { yeild return new modelvalidateresult
{ message=validation.errormessage; }; yeild break; } } protect internal string errormessage { get{ return this.attribute.formaterrormessage(base.metadata.dispalyname()); } } }
下一篇: 杰和数字标牌在寻路导航方面的应用