• <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
    主站蜘蛛池模板: 精品欧洲av无码一区二区三区| 精品无人码麻豆乱码1区2区| 精品成在人线AV无码免费看 | 亚洲国产人成精品 | 99久久这里只有精品| 国产专区日韩精品欧美色| 国产成人精品男人的天堂538| 亚洲七七久久精品中文国产| 国产成人无码精品久久久久免费| 99国产精品无码| 亚洲国产精品久久电影欧美| 久久精品国产色蜜蜜麻豆| 99久久婷婷国产综合精品草原| 99精品国产高清一区二区麻豆 | 久久久精品国产Sm最大网站| 欧美亚洲国产成人精品| 国产AV国片精品有毛| 亚洲AV午夜福利精品一区二区| 久久se精品一区二区影院 | 伊人久久精品影院| 久久久久久久亚洲精品| 国产精品免费大片一区二区| 亚洲精品无码不卡| 国内精品手机在线观看视频| 国产亚洲欧美精品久久久| 色国产精品一区在线观看| 合区精品中文字幕| 久久久久成人精品无码| 精品无码人妻一区二区三区不卡| 国产精品一区二区久久精品无码 | 国产AV午夜精品一区二区三区 | 国产高清国产精品国产专区| 精品国产三级a在线观看| 少妇精品无码一区二区三区| 久久精品亚洲中文字幕无码麻豆| 亚洲精品国精品久久99热一| 亚洲精品无码你懂的网站| 亚洲国产精品尤物yw在线| 亚洲欧美日韩久久精品第一区 | 国产精品999| 九九精品成人免费国产片|