前言c#
前面一篇讲解了Model元数据,Model元数据是在Model绑定中很重要的一部分,只是Model绑定中涉及的知识点比较多,对于ASP.NET MVC框架来讲ASP.NET Web API框架中在Model绑定部分又新增了参数绑定这么一个机制,这些内容都会在后面的篇幅中说明,前面的这些篇幅都是讲解理论上的知识也没有涉及到示例的演示,这个你们不用急在最后Model部分的基础知识讲解完以后我会把前面所讲的所有串联起来,而今天这个篇幅给你们带来的就是在Model绑定中起到相当重要的一个环节,你们这个不用去管什么Model绑定,而是单纯的去了解ValueProvider这一系列的对象模型,由于在没有结合先后知识点串联起来以前,咱们都不知道ValueProvider是在哪执行的。因此咱们仍是老老实实了解一下ValueProvider相关的对象吧。框架
Model-ValueProvideride
图1函数
IValueProvider接口类型--ValueProvider行为约束ui
首先咱们看一下图1中右边的部分,起头的就是一个IValueProvider接口类型,咱们就来看一下接口的定义:spa
示例代码1-1对象
publicinterfaceIValueProvider { boolContainsPrefix(stringprefix); ValueProviderResultGetValue(stringkey); }
咱们在代码1-1中看到,IValueProvider接口中定义了两个方法,一个是ContainsPrefix()方法,接收string类型的参数而且返回的是bool值类型,这个方法表示的就是根据指定的前缀值查看当前的ValueProvider中是否存在这个前缀值,这个下面会有示例稍后再说,而后就是GetValue()方法,是根据执行的键值返回当中的对应的值,从这里一看咱们就大概能猜到这个ValueProvider应该是相似于键值队同样的类型,而返回的结果被封装在了ValueProviderResult类型当中,这个类型稍后会有说明。在IValueProvider接口约束好ValueProvider值提供程序的行为后,咱们应该就来看一看ValueProvider值提供程序的基础结构了。不过呢在此以前咱们仍是要根据图1中所示的那样,先来看一下IEnumerableValueProvider接口类型的定义,这个接口主要负责什么呢?blog
IEnumerableValueProvider接口类型-ValueProvider行为约束接口
示例代码1-2ip
publicinterfaceIEnumerableValueProvider : IValueProvider { IDictionary<string, string>GetKeysFromPrefix(stringprefix); }
从代码1-2中能够很清楚明了的看到IEnumerableValueProvider接口类型的职责很简单,就是对指定的前缀值进行检索,而且最后以键值队的形式返回,这个在下面会有示例详细说明。
NameValuePairsValueProvider类型-ValueProvider基础结构
示例代码1-3
publicclassNameValuePairsValueProvider : IEnumerableValueProvider, IValueProvider { publicNameValuePairsValueProvider(Func<IEnumerable<KeyValuePair<string, string>>>valuesFactory, CultureInfoculture); publicNameValuePairsValueProvider(IEnumerable<KeyValuePair<string, string>>values, CultureInfoculture); publicvirtualboolContainsPrefix(stringprefix); publicvirtualIDictionary<string, string>GetKeysFromPrefix(stringprefix); publicvirtualValueProviderResultGetValue(stringkey); }
在代码1-3中咱们看到NameValuePairsValueProvider类型的定义,首先就说说它的构造函数吧,两个构造函数的区别在于第一个是Func<IEnumerable<KeyValuePair<string, string>>>类型的构造函数参数,第二个是IEnumerable<KeyValuePair<string, string>>类型的构造函数参数,第二个构造函数的首个参数类型实际就是第一个构造函数首个参数的返回类型,这里你们都看获得,其实在内部实现,也是这样的声明第一个构造函数是没什么的,声明第二个构造函数的时候其实就把参数再次封装为委托。
对于KeyValuePair<T,U>类型能够理解为键值队的子项,在它的类型中只有一个键值对应一个值只有一项就是它自己。
至于剩下的三个方法咱们仍是靠简单的示例来讲明一下。
示例代码1-4
publicclassValueProviderCaseController : ApiController { publicstringGet() { KeyValuePair<string,string>[] dictionary=newKeyValuePair<string,string>[] { newKeyValuePair<string,string>("EmployeesInfo.Name","Jinyuan"), newKeyValuePair<string,string>("EmployeesInfo.Age","24"), newKeyValuePair<string,string>("EmployeesInfo.Sex","男"), newKeyValuePair<string,string>("EmployeesInfo.AddressInfo.AddressInfo","南京市"), newKeyValuePair<string,string>("EmployeesInfo.AddressInfo.ZipCode","210000") }; NameValuePairsValueProvidernameValuePairsValueProvider=newNameValuePairsValueProvider(dictionary,null); StringBuilderstrBuilder=newStringBuilder(); NameValuePairsPrefixAnalysis(strBuilder, nameValuePairsValueProvider, "EmployeesInfo"); returnstrBuilder.ToString(); } privatevoidNameValuePairsPrefixAnalysis(StringBuilderstringbuilder, NameValuePairsValueProvidernamevaluepairs,stringprefix) { IDictionary<string, string>dictionarys=namevaluepairs.GetKeysFromPrefix(prefix); if (dictionarys.Count>0) { Console.WriteLine(prefix+"为前缀的数据源Key值检索……"); foreach (varitemindictionarys) { Console.WriteLine("Key:"+item.Key+" Value:"+item.Value); } foreach (KeyValuePair<string, string>keyvalueindictionarys) { NameValuePairsPrefixAnalysis(stringbuilder, namevaluepairs, keyvalue.Value); } } else { stringbuilder.AppendLine(prefix+":"+namevaluepairs.GetValue(prefix).RawValue.ToString()); } } }
咱们来看代码1-4,首先我在Get()方法中定义了一个KeyValuePair<string,string>[]类型,为了可以实例化NameValuePairsValueProvider类型,在此以后你们能够看到我调用了一个我自定义的NameValuePairsPrefixAnalysis()方法,而且在其中使用NameValuePairsValueProvider类型的实例调用了GetKeysFromPrefix()方法,也就是代码1-2所约束的那个行为。这个时候咱们先来看一下表1.
表1
Key |
Value |
EmployeesInfo.Name |
Jinyuan |
EmployeesInfo.Age |
24 |
EmployeesInfo.Sex |
男 |
EmployeesInfo.AddressInfo.AddressInfo |
南京市 |
EmployeesInfo.AddressInfo.ZipCode |
210000 |
表1所表示的就是初始数据源,也就是咱们定义的KeyValuePair<string,string>[]类型的键、值示意表。
然而在咱们使用NameValuePairsValueProvider类型的实例已” EmployeesInfo”做为前缀调用了GetKeysFromPrefix()方法后返回的IDictionary<string,string>类型的值如表2.
表2
Key |
Value |
Name |
EmployeesInfo.Name |
Age |
EmployeesInfo.Age |
Sex |
EmployeesInfo.Sex |
AddressInfo |
EmployeesInfo.AddressInfo |
这里的表2值只是第一层的关系值。
在此以后咱们输出的当前的所要检索的前缀值以及检索事后的值,而且会遍历表2里的Value值做为前缀值再次的对数据源进行前缀检索,若是没有了则说明已经没有可检索的了。
而且使用NameValuePairsValueProvider类型实例调用的GetValue()方法根据最后已经检索不出来有后缀的前缀值,也就是原始数据源当中的Key值了。
最后咱们看一下结果。
图2
在客户端咱们获取到了值,固然这里只是演示示例,值提供程序提供的值方向反了。
而后咱们能够在服务端看到检索的记录,能够明确的看到有两层的结构在其中。有兴趣的朋友深刻一下看下检索的具体实现方式。
QueryStringValueProvider类型-ValueProvider特定结构
示例代码1-5
publicclassQueryStringValueProvider : NameValuePairsValueProvider { publicQueryStringValueProvider(HttpActionContextactionContext, CultureInfoculture) : base(func, culture) { Func<IEnumerable<KeyValuePair<string, string>>>func=null; if (func==null) { func= () =>actionContext.ControllerContext.Request.GetQueryNameValuePairs(); } } }
从代码1-5中能够看到在QueryStringValueProvider类型初始化的时候构造函数中的执行,把从请求查询字符串做为原始数据来源封装为委托类型,而后调用基类的构造函数。
RouteDataValueProvider类型-ValueProvider特定结构
示例代码1-6
publiccla***outeDataValueProvider : NameValuePairsValueProvider { publicRouteDataValueProvider(HttpActionContextactionContext, CultureInfoculture) : base(func, culture) { Func<IEnumerable<KeyValuePair<string, string>>>func=null; if (func==null) { func= () =>GetRoutes(actionContext.ControllerContext.RouteData); } } }
同上面1-5同样的道理,这里使用了HttpRouteData中的Values值做为原始数据源。
还有图1中的左边部分会在后面的篇幅中讲解,在这里讲不适合,会感受不连贯,虽然看完本篇不知道这个起到了什么做用也不知道怎么去使用,感受被掐住了脖子同样的难受,可是后面我会把前面所讲的内容所有串联起来作一个演示,所示这是基础部分的知识,就是一个铺垫。