• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    ASP.NET Core中如何使用表達式樹創建URL詳解

    來源:懂視網 責編:小采 時間:2020-11-27 22:34:44
    文檔

    ASP.NET Core中如何使用表達式樹創建URL詳解

    ASP.NET Core中如何使用表達式樹創建URL詳解:表達式樹(Expression Tree) 表達式樹是不可執行的代碼,它只是用于表示一種樹狀的數據結構,樹上的每一個節點都表示為某種表達式類型,大概有25種表達式類型,它們都派生自Expression類。創建表達式樹具體有兩個優勢: 1.對表達式樹的代碼進行編輯修改,使
    推薦度:
    導讀ASP.NET Core中如何使用表達式樹創建URL詳解:表達式樹(Expression Tree) 表達式樹是不可執行的代碼,它只是用于表示一種樹狀的數據結構,樹上的每一個節點都表示為某種表達式類型,大概有25種表達式類型,它們都派生自Expression類。創建表達式樹具體有兩個優勢: 1.對表達式樹的代碼進行編輯修改,使

    表達式樹(Expression Tree)

    表達式樹是不可執行的代碼,它只是用于表示一種樹狀的數據結構,樹上的每一個節點都表示為某種表達式類型,大概有25種表達式類型,它們都派生自Expression類。創建表達式樹具體有兩個優勢:

    1.對表達式樹的代碼進行編輯修改,使表達式樹中的代碼變成動態代碼,根據不同的數據庫修改樹上的代碼邏輯從而達到動態切換數據庫查詢語句的目的,用表達式樹可以動態構建針對不同數據庫的查詢語句。

    2.完成類似反射訪問未知對象的屬性,通過動態構造表達式樹,生成委托。

    當我們在ASP.NET Core中生成一個action的url會這樣寫:

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

    這樣的寫法存在的問題在于我們傳遞了兩個字符串類型的參數,而我們又無法避免對action和controller做重命名操作, 例如將index重命名為default, 你無法通過IDE在重命名action的過程中,將

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

    重構為

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

    所以我們的目標是:設計出具有靜態檢查的API,讓IDE提示出這個錯誤來,甚至是重命名時直接把相關代碼都能重命名。

    目標

    設計出類似兩組API:

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

    設計API

    根據上面的需求,定義兩組API:

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

    實現API

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

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

    所以問題變成了如何根據(HomeController c) => c.Index()這樣的表達式來解析出actionName, ControllerName以及routeValues。

    1. 解析ControllerName

    解析ControllerName比較簡單粗暴,因為我們已經從表達式樹中得到了HomeController這個類型,直接取 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

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

    private static MethodCallExpression
    GetMethodCallExpression<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

    上面兩步已經解析出了ControllerName和ActionName,也就是說通過上面的分析已經能完成下面的調用:

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

    但是考慮下面的Action:

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

    這個Action期待傳入一個int類型的id,也就是說你要通過這樣的方式來生成url:

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

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

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

    要想生成這個匿名對象,需要遍歷方法調用表達式的所有參數,分別解析出屬性名,例如id; 以及值,例如10。最后再把解析出來的參數字典生成為dynamic類型的對象:

    如何解析表達式樹請查看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;
     }
    }

    一個完整的API實現:

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

    總結

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    ASP.NET Core中如何使用表達式樹創建URL詳解

    ASP.NET Core中如何使用表達式樹創建URL詳解:表達式樹(Expression Tree) 表達式樹是不可執行的代碼,它只是用于表示一種樹狀的數據結構,樹上的每一個節點都表示為某種表達式類型,大概有25種表達式類型,它們都派生自Expression類。創建表達式樹具體有兩個優勢: 1.對表達式樹的代碼進行編輯修改,使
    推薦度:
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 欧美亚洲成人精品| 国产精品美脚玉足脚交欧美| 人妻少妇精品视频二区| 99热日韩这里只有精品| 国产成人精品电影在线观看| 一本之道av不卡精品| 国产综合精品蜜芽| 亚洲国产精品自在在线观看| 人妻精品久久久久中文字幕69| 欧美精品一区二区三区免费观看 | 国产精品成人不卡在线观看| 亚洲精品乱码久久久久久蜜桃图片| 国产精品无码一区二区在线 | 国产精品热久久毛片| 精品一区二区三区中文字幕| 国产在线精品免费aaa片| 亚洲av无码乱码国产精品fc2 | 国产精品片在线观看手机版| 久久精品一区二区三区不卡| 国产精品看高国产精品不卡| 久久精品夜夜夜夜夜久久| 伊人久久大香线蕉精品不卡| 日韩在线精品一二三区| 国产一在线精品一区在线观看| 2021最新国产精品一区| 四虎精品成人免费永久| 柠檬福利精品视频导航| 久久99精品国产麻豆宅宅| 久久国产精品-国产精品| 精品成人免费自拍视频| 久久91精品国产91久久小草| 国产精品素人搭讪在线播放| 成人精品综合免费视频| 国产小视频国产精品| 免费欧美精品a在线| 99热精品久久只有精品| 国产乱人伦偷精品视频不卡| 精品日本一区二区三区在线观看| 国产在线精品福利大全| 人妻少妇精品久久| 最新精品亚洲成a人在线观看|