表達(dá)式樹(Expression Tree)
表達(dá)式樹是不可執(zhí)行的代碼,它只是用于表示一種樹狀的數(shù)據(jù)結(jié)構(gòu),樹上的每一個節(jié)點都表示為某種表達(dá)式類型,大概有25種表達(dá)式類型,它們都派生自Expression類。創(chuàng)建表達(dá)式樹具體有兩個優(yōu)勢:
1.對表達(dá)式樹的代碼進(jìn)行編輯修改,使表達(dá)式樹中的代碼變成動態(tài)代碼,根據(jù)不同的數(shù)據(jù)庫修改樹上的代碼邏輯從而達(dá)到動態(tài)切換數(shù)據(jù)庫查詢語句的目的,用表達(dá)式樹可以動態(tài)構(gòu)建針對不同數(shù)據(jù)庫的查詢語句。
2.完成類似反射訪問未知對象的屬性,通過動態(tài)構(gòu)造表達(dá)式樹,生成委托。
當(dāng)我們在ASP.NET Core中生成一個action的url會這樣寫:
var url=_urlHelper.Action("Index", "Home");這樣的寫法存在的問題在于我們傳遞了兩個字符串類型的參數(shù),而我們又無法避免對action和controller做重命名操作, 例如將index重命名為default, 你無法通過IDE在重命名action的過程中,將
_urlHelper.Action("Index", "Home");重構(gòu)為
UrlHelper.Action("Default", "Home");所以我們的目標(biāo)是:設(shè)計出具有靜態(tài)檢查的API,讓IDE提示出這個錯誤來,甚至是重命名時直接把相關(guān)代碼都能重命名。
目標(biāo)
設(shè)計出類似兩組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è)計API
根據(jù)上面的需求,定義兩組API:
public static string Action<TController>(this IUrlHelper helper, Expression<Action<TController>> action)where TController : Controller{ //實現(xiàn)}public static string Link<TController>(this IUrlHelper helper, Expression<Action<TController>> action,string protocal = null, string host = null)where TController : Controller{ //實現(xiàn)}實現(xiàn)API
我們實際上最終還是要依賴ASP.NET Core提供的API:
var link = helper.Action(action: actionName, controller: controllerName, values: routes);
所以問題變成了如何根據(jù)(HomeController c) => c.Index()這樣的表達(dá)式來解析出actionName, ControllerName以及routeValues。
1. 解析ControllerName
解析ControllerName比較簡單粗暴,因為我們已經(jīng)從表達(dá)式樹中得到了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;}
新聞熱點
疑難解答
圖片精選