日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

      歡迎訪問(wèn) 生活随笔!

      生活随笔

      當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

      asp.net

      ASP.NET Core中使用表达式树创建URL

      發(fā)布時(shí)間:2023/12/4 asp.net 39 豆豆
      生活随笔 收集整理的這篇文章主要介紹了 ASP.NET Core中使用表达式树创建URL 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

      當(dāng)我們?cè)贏SP.NET Core中生成一個(gè)action的url會(huì)這樣寫(xiě):


      var?url=_urlHelper.Action("Index", "Home");

      這樣的寫(xiě)法存在的問(wèn)題在于我們傳遞了兩個(gè)字符串類(lèi)型的參數(shù),而我們又無(wú)法避免對(duì)action和controller做重命名操作, 例如將index重命名為default, 你無(wú)法通過(guò)IDE在重命名action的過(guò)程中,將


      _urlHelper.Action("Index", "Home");

      重構(gòu)為


      UrlHelper.Action("Default", "Home");

      所以我們的目標(biāo)是:設(shè)計(jì)出具有靜態(tài)檢查的API,讓IDE提示出這個(gè)錯(cuò)誤來(lái),甚至是重命名時(shí)直接把相關(guān)代碼都能重命名。


      目標(biāo)

      設(shè)計(jì)出類(lèi)似兩組API:


      var?url = _urlHelper.Action((HomeController c) => c.Index());//期待輸出 /home/indexvar?link = _urlHelper.Link((ProductController c) => c.Details(10));//期待輸出 http://locahost/product/details/10


      設(shè)計(jì)API

      根據(jù)上面的需求,定義兩組API:


      public?static?string?Action<TController>(this?IUrlHelper helper,Expression<Action<TController>> action)where?TController : Controller{//實(shí)現(xiàn)}public?static?string?Link<TController>(this?IUrlHelper helper,Expression<Action<TController>> action,string?protocal = null, string?host = null)where?TController : Controller{//實(shí)現(xiàn)}


      實(shí)現(xiàn)API

      我們實(shí)際上最終還是要依賴ASP.NET Core提供的API:


      var?link = helper.Action(action: actionName, controller:controllerName, values: routes);

      所以問(wèn)題變成了如何根據(jù)(HomeController c) => c.Index()這樣的表達(dá)式來(lái)解析出actionName, ControllerName以及routeValues。

      1. 解析ControllerName

      解析ControllerName比較簡(jiǎn)單粗暴,因?yàn)槲覀円呀?jīng)從表達(dá)式樹(shù)中得到了HomeController這個(gè)類(lèi)型,直接取Home字符串即可:


      private?static?string?GetControllerName(Type controllerType){var?controllerName = controllerType.Name.EndsWith("Controller")? controllerType.Name.Substring(0,controllerType.Name.Length - "Controller".Length): controllerType.Name;return?controllerName;}

      2. 解析ActionName

      由于表達(dá)式(HomeController c) => c.Index()是一個(gè)MethodCallExpression類(lèi)型,而Action的名字就是方法名:


      private?static?MethodCallExpressionGetMethodCallExpression<TController>(Expression<Action<TController>> actionSelector){var?call = actionSelector.Body as?MethodCallExpression;if?(call == null){throw?new?ArgumentException("You must call a method on "?+typeof(TController).Name, "actionSelector");}return?call;}var?methodCallExpression = GetMethodCallExpression(action);var?actionName = methodCallExpression.Method.Name;

      3. 解析RouteValues

      上面兩步已經(jīng)解析出了ControllerName和ActionName,也就是說(shuō)通過(guò)上面的分析已經(jīng)能完成下面的調(diào)用:


      var?action = helper.Action(action: "index", controller: "home", values: null);//等價(jià)于var?url = _urlHelper.Action((HomeController c) => c.Index());//輸出 /home/index

      但是考慮下面的Action:


      [HttpGet,Route("product/{id}")]public?IActionResult Details(int?id){//...}

      這個(gè)Action期待傳入一個(gè)int類(lèi)型的id,也就是說(shuō)你要通過(guò)這樣的方式來(lái)生成url:


      var?action = helper.Action(action: "details", controller:"product", values: new?{ id = 10 });

      所以要想讓我們的API正常工作,還需要生成一個(gè)object類(lèi)型:new { id = 10 }。而這個(gè)object類(lèi)型里面的屬性正好可以來(lái)自于表達(dá)式樹(shù)的方法調(diào)用參數(shù):


      var?action = _urlHelper.Action((ProductController c) => c.Details(10));

      要想生成這個(gè)匿名對(duì)象,需要遍歷方法調(diào)用表達(dá)式的所有參數(shù),分別解析出屬性名,例如id; 以及值,例如10。最后再把解析出來(lái)的參數(shù)字典生成為dynamic類(lèi)型的對(duì)象:
      如何解析表達(dá)式樹(shù)請(qǐng)查看expression-trees。


      public?class?RouteValueExtractor{public?static?object?GetRouteValues(MethodCallExpression call){var?routes = new?Dictionary<string, object>();var?parameters = call.Method.GetParameters();var?pairs = call.Arguments.Select((a, i) => new{Argument = a,ParamName = parameters[i].Name});foreach?(var?item in?pairs){string?name = item.ParamName;object?value = GetValue(item.Argument);if?(value != null){var?valueType = value.GetType();if?(valueType.IsValueType){routes.Add(name, value);}else{throw?new?NotSupportedException("Unsupported parameter type {0}");}}}return?DictionaryToObject(routes);}private?static?object?GetValue(Expression expression){if?(expression.NodeType == ExpressionType.Constant){return?((ConstantExpression) expression).Value;}throw?new?NotSupportedException("Unsupported parameter expression");}private?static?dynamic DictionaryToObject(IDictionary<string, object> dictionary){var?expandoObj = new?ExpandoObject();var?expandoObjCollection = (ICollection<KeyValuePair<string, object>>) expandoObj;foreach?(var?keyValuePair in?dictionary){expandoObjCollection.Add(keyValuePair);}dynamic eoDynamic = expandoObj;return?eoDynamic;}}

      一個(gè)完整的API實(shí)現(xiàn):


      public?static?string?Action<TController>(this?IUrlHelper helper,Expression<Action<TController>> action)where?TController : Controller{var?controllerName = GetControllerName(typeof(TController));var?methodCallExpression = GetMethodCallExpression(action);var?actionName = methodCallExpression.Method.Name;var?routes = RouteValueExtractor.GetRouteValues(methodCallExpression);var?link = helper.Action(action: actionName, controller:controllerName, values: routes);return?link;}

      原文地址:?https://www.cnblogs.com/xiandnc/p/9746274.html


      .NET社區(qū)新聞,深度好文,歡迎訪問(wèn)公眾號(hào)文章匯總 http://www.csharpkit.com

      總結(jié)

      以上是生活随笔為你收集整理的ASP.NET Core中使用表达式树创建URL的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

      如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。