当前位置: 移动技术网 > IT编程>开发语言>.net > ModelValidator基于元数据的验证

ModelValidator基于元数据的验证

2018年09月21日  | 移动技术网IT编程  | 我要评论

快乐大本营120818,中星6b本振频率,宋茜 昌珉

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()); } } }

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网