|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
有时也搞不懂应该学那种;主要看你以后去的那个公司是使用哪种了。就像王千祥的课上说的:企业应用现在主要就三层(其实也差不多就是MVC):表示层(主要使用html写的,很简单)、业务逻辑层(主要就是应用服务器的)。最后就是数据层(其实就是学习数据库)写了博文ASP.NETMVC3晋级至MVC5.1的遭受:“已增加了具有不异键的项”以后,持续看着System.Web.Mvc.JsonValueProviderFactory的开源代码。
越看越不扎眼,越看内心越不爽!不爽的中央次要有两个:
1)仍然在利用用功能低下且不开源的JavaScriptSerializer!打逝世也不必Json.NET!
2)作为一个工场类,JsonValueProviderFactory完成庞大,并且工场临盆出的产物DictionaryValueProvider(IValueProvider的一个完成)也很庞大。
【先看第一个不爽】
JsonValueProviderFactory的事情之一是对json字符串举行反序列化,而Json.NET的反序列化功能远超JavaScriptSerializer,请看下图:
而微软MVC开辟职员仍然不思朝上进步,用自家工具的痴心不改,持续用着JavaScriptSerializer。
- privatestaticobjectGetDeserializedObject(ControllerContextcontrollerContext){//...JavaScriptSerializerserializer=newJavaScriptSerializer();objectjsonData=serializer.DeserializeObject(bodyText);returnjsonData;}
复制代码
仅凭这一点,就让我发生了如许的感动——基于Json.NET本人完成一个JsonValueProviderFactory。
【再看第二个不爽】
作为一个工场类,JsonValueProviderFactory承继自ValueProviderFactory,重载了ValueProviderFactory的笼统办法GetValueProvider,前往接口IValueProvider的一个完成。(ControllerActionInvoker就是经由过程IValueProvider接口依据key失掉Action各个参数的值)
IValueProvider的代码以下:
- namespaceSystem.Web.Mvc{publicinterfaceIValueProvider{boolContainsPrefix(stringprefix);ValueProviderResultGetValue(stringkey);}}
复制代码
接口很复杂,先反省prefix是不是存在,假如存在经由过程key取值。
JsonValueProviderFactory前往的DictionaryValueProvider就是干这个活的,可是为了临盆DictionaryValueProvider,JsonValueProviderFactory举行了庞大的搬箱子操纵,不但用到了递回,并且还用了多个IDictionary<string,object>,代码让人看得头晕。
再看看DictionaryValueProvider的完成,也是庞大,并且还用到了PrefixContainer。
复杂算个账:JsonValueProviderFactory的代码用了120行,DictionaryValueProvider的代码用了63行,PrefixContainer的代码用了219,一共用了402行代码(包括空行与定名空间的援用)。有些奢靡!
必要这么庞大吗?有更复杂的办理办法吗?
【感动不如举动】
办理成绩的关头在于怎样以更复杂的办法完成IValueProvider的两个操纵——ContainsPrefix与GetValue。
要完成这两个操纵,先要摸清prefix与key的纪律。因而先完成一个MockValueProvider,经由过程日记纪录ControllerActionInvoker挪用这个接口时利用的参数。
经由过程日记信息,找出了如许的纪律:
1.假如Action的参数是如许的:- publicActionResultPostList(AggSiteModelmodel){}
复制代码 ControllerActionInvoker会如许挪用:
ContainsPrefix("model")->假如前往False->以AggSiteModel的属性称号顺次ContainsPrefix,好比ContainsPrefix("PageTitle")【注:PageTitle是AggSiteModel的一个属性】->假如前往True->会以prefix为key挪用GetValue。
2.假如Action的参数是数组:- publicActionResultPostList(AggSiteModel[]model){}
复制代码 ControllerActionInvoker会如许挪用:
ContainsPrefix("[0]")->假如前往True->ContainsPrefix("[0].PageTitle")->假如前往True->GetValue("[0].PageTitle")
3.仍然是第1种的Action参数情势,只不外AggSiteModel有聚合。- publicclassAggSiteModel{publicstringPageTitle{get;set;}publicPagingBuilderPaging{get;set;}}
复制代码 ControllerActionInvoker会如许挪用:
ContainsPrefix("model")->假如前往False->ContainsPrefix("Paging.PageTitle")
看到这些key的特性,想到了Json.NET中的SelectTokens:
- ///<summary>///SelectsacollectionofelementsusingaJPathexpression.///</summary>///<paramname="path">///A<seecref="String"/>thatcontainsaJPathexpression.///</param>///<returns>An<seecref="IEnumerable{JToken}"/>thatcontainstheselectedelements.</returns>publicIEnumerable<JToken>SelectTokens(stringpath){returnSelectTokens(path,false);}
复制代码
这是里key居然与JPath惊人的类似!
看来Json.NET不但能够弄定JsonValueProviderFactory,还能够弄定DictionaryValueProvider+PrefixContainer,完成代码应当不会凌驾100行。
【基于Json.NET完成CnblogsJsonValueProviderFactory】
- publicclassCnblogsJsonValueProviderFactory:ValueProviderFactory{publicoverrideIValueProviderGetValueProvider(ControllerContextcontrollerContext){if(controllerContext==null)thrownewArgumentNullException("controllerContext");if(!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json",StringComparison.OrdinalIgnoreCase)){returnnull;}varbodyText=string.Empty;using(varreader=newStreamReader(controllerContext.HttpContext.Request.InputStream)){bodyText=reader.ReadToEnd();}if(string.IsNullOrEmpty(bodyText))returnnull;returnnewJObjectValueProvider(bodyText.StartsWith("[")?JArray.Parse(bodyText)asJContainer:JObject.Parse(bodyText)asJContainer);}}publicclassJObjectValueProvider:IValueProvider{privateJContainer_jcontainer;publicJObjectValueProvider(JContainerjcontainer){_jcontainer=jcontainer;}publicboolContainsPrefix(stringprefix){return_jcontainer.SelectToken(prefix)!=null;}publicValueProviderResultGetValue(stringkey){varjtoken=_jcontainer.SelectToken(key);if(jtoken==null||jtoken.Type==JTokenType.Object)returnnull;returnnewValueProviderResult(jtoken.ToObject<object>(),jtoken.ToString(),CultureInfo.CurrentCulture);}}
复制代码
包括空行与定名空间的援用,一共只要61行代码,远远少于MVC中的402行代码。
在项目中利用这个CnblogsJsonValueProviderFactory:
- protectedvoidApplication_Start(Objectsender,EventArgse){ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());ValueProviderFactories.Factories.Add(newCnblogsJsonValueProviderFactory());}
复制代码
【十全十美】
Json.NET中的SelectTokens的path参数辨别巨细写,利用CnblogsJsonValueProviderFactory,在js中写json时,巨细写必需要婚配。
看了一下Json.NET的开源代码,发明是与上面的代码有关:- internalclassJPropertyKeyedCollection:Collection<JToken>{privatestaticreadonlyIEqualityComparer<string>Comparer=StringComparer.Ordinal;}
复制代码 假如把StringComparer.Ordinal改成StringComparer.OrdinalIgnoreCase就可以办理成绩,可是不晓得会不会给Json.NET的功能带来影响。
严厉辨别巨细写也能承受,可让代码更标准一些。
听03很多师兄说主讲老师杭城方讲课很差就连旁听也没有去了) |
|