• <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久久精品免费观看国产| 精品国产免费一区二区三区| 国产精品欧美亚洲韩国日本| 日韩福利视频精品专区| 91po国产在线精品免费观看| 狼色精品人妻在线视频| 精品久久久久久久久久久久久久久| 精品不卡一区二区| 在线精品亚洲一区二区三区| 国产亚洲精品高清在线| 久久99精品国产| 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 国产成人精品午夜福利| 亚洲精品无码午夜福利中文字幕 | 91精品最新国内在线播放| 中文精品久久久久人妻| 久久精品国产一区二区三区不卡 | 久久国产精品99精品国产987| 久久99国产乱子伦精品免费| 亚洲精品专区在线观看| 日韩精品无码永久免费网站| 久久精品国产欧美日韩| 国产精品亚洲综合一区| 国产高清在线精品一区二区 | 无码国内精品人妻少妇| 欲帝精品福利视频导航| 亚洲国产精品一区二区九九| 青春草无码精品视频在线观| 欧美在线精品一区二区三区| 麻豆精品国产自产在线观看一区| 国内精品久久久久久不卡影院| 国产成人精品综合久久久| 8050免费午夜一级国产精品| 四虎影视国产精品永久在线| 亚洲精品免费观看| 国产精品99无码一区二区 | 久久精品九九亚洲精品天堂| 2020久久精品国产免费| 99爱在线精品免费观看| 九九精品99久久久香蕉| 精品国产乱码久久久久久1区2区 |