C# 通過Dynamic訪問System.Text.Json對(duì)象
?有時(shí)在處理Http請(qǐng)求的時(shí)候,偷懶不想定義一個(gè)Model來處理,使用Dynamic來直接操作請(qǐng)求的數(shù)據(jù)是非常方便的
C#中dynamic關(guān)鍵字
?dynamic關(guān)鍵字和動(dòng)態(tài)語言運(yùn)行時(shí)(DLR)是.Net 4.0中新增的功能。
什么是"動(dòng)態(tài)"
編程語言有時(shí)可以劃分為靜態(tài)類型化語言和動(dòng)態(tài)類型化語言。C#和Java經(jīng)常被認(rèn)為是靜態(tài)化類型的語言,而Python、Ruby和JavaScript是動(dòng)態(tài)類型語言。
一般而言,動(dòng)態(tài)語言在編譯時(shí)不會(huì)對(duì)類型進(jìn)行檢查,而是在運(yùn)行時(shí)識(shí)別對(duì)象的類型。這種方法有利有弊:代碼編寫起來更快、更容易,但無法獲取編譯器錯(cuò)誤,只能通過單元測試和其他方法來確保應(yīng)用正常運(yùn)行。
C#最初是作為純靜態(tài)語言創(chuàng)建的,但是C#4添加了一些動(dòng)態(tài)元素,用于改進(jìn)與動(dòng)態(tài)語言和框架之間的互操作性。C# 團(tuán)隊(duì)考慮了多種設(shè)計(jì)選項(xiàng),但最終確定添加一個(gè)新關(guān)鍵字來支持這些功能:dynamic。
dynamic關(guān)鍵字可充當(dāng)C#類型系統(tǒng)中的靜態(tài)類型聲明。這樣,C#就獲得了動(dòng)態(tài)功能,同時(shí)仍然作為靜態(tài)類型化語言而存在。由于編譯時(shí)不會(huì)去檢查類型,所以導(dǎo)致IDE的IntellSense失效。
dynamic、object還是var?
那么,dynamic、Object和var之間的實(shí)際區(qū)別是什么?何時(shí)使用它們?
先說說var,經(jīng)常有人會(huì)拿dynamic和var進(jìn)行比較。實(shí)際上,var和dynamic完全是兩個(gè)概念,根本不應(yīng)該放在一起做比較。
var實(shí)際上編譯器拋給我們的語法糖,一旦被編譯,編譯器就會(huì)自動(dòng)匹配var變量的實(shí)際類型,并用實(shí)際類型來替換該變量的聲明,等同于我們在編碼時(shí)使用了實(shí)際類型聲明。而dynamic被編譯后是一個(gè)Object類型,編譯器編譯時(shí)不會(huì)對(duì)dynamic進(jìn)行類型檢查。
再說說Object,上面提到dynamic類型再編譯后是一個(gè)Object類型,同樣是Object類型,那么兩者的區(qū)別是什么呢?
除了在編譯時(shí)是否進(jìn)行類型檢查之外,另外一個(gè)重要的區(qū)別就是類型轉(zhuǎn)化,這也是dynamic很有價(jià)值的地方,dynamic類型的實(shí)例和其他類型的實(shí)例間的轉(zhuǎn)換是很簡單的,開發(fā)人員能夠很方便地在dyanmic和非dynamic行為間切換。任何實(shí)例都能隱式轉(zhuǎn)換為dynamic類型實(shí)例,見下面的例子:
dynamic?d1?=?7;
dynamic?d2?=?"a?string";
dynamic?d3?=?System.DateTime.Today;
dynamic?d4?=?System.Diagnostics.Process.GetProcesses();
反之亦然,類型為dynamic的任何表達(dá)式也能夠隱式轉(zhuǎn)換為其他類型。
int?i?=?d1;
string?str?=?d2;
DateTime?dt?=?d3;
System.Diagnostics.Process[]?procs?=?d4;
前面整理過一篇關(guān)于dynamic類型與Newtonsoft.Json來操作請(qǐng)求的數(shù)據(jù),請(qǐng)參考如下文章
C# Dynamic與Newtonsoft.Json的應(yīng)用
參考Nettonsoft.Json中的訪問,同樣定義一個(gè)JTextAccessor,代碼如下
?dynamic是C#里面的動(dòng)態(tài)類型,可在未知類型的情況訪問對(duì)應(yīng)的屬性,非常靈活和方便。如果有已知強(qiáng)類型,如果有已知對(duì)應(yīng)的強(qiáng)類型,可以直接轉(zhuǎn)成對(duì)應(yīng)的類型。但如果沒有,要訪問Json里面對(duì)應(yīng)的數(shù)據(jù)的時(shí)候,就顯得比較麻煩。再根據(jù)Asp.Net Core WebAPI中的FromBody傳遞內(nèi)容就是一個(gè)JsonElement,我們可以借助DynamicObject來方便的訪問對(duì)應(yīng)的屬性。
public?class?JTextAccessor?:?DynamicObject
{
????private?readonly?JsonElement?_content;
????public?JTextAccessor(JsonElement?content)
????{
????????_content?=?content;
????}
????public?override?bool?TryGetMember(GetMemberBinder?binder,?out?object??result)
????{
????????result?=?null;
????????if?(_content.TryGetProperty(binder.Name,?out?JsonElement?value))
????????{
????????????result?=?Obtain(value);
????????}
????????else?return?false;
????????return?true;
????}
????private?object??Obtain(in?JsonElement?element)
????{
????????switch?(element.ValueKind)
????????{
????????????case?JsonValueKind.String:?return?element.GetString();
????????????case?JsonValueKind.Null:?return?null;
????????????case?JsonValueKind.False:?return?false;
????????????case?JsonValueKind.True:?return?true;
????????????case?JsonValueKind.Number:?return?element.GetDouble();
????????????default:?break;
????????}
????????if?(element.ValueKind?==?JsonValueKind.Array)
????????{
????????????var?list?=?new?List<object>();
????????????foreach?(var?item?in?element.EnumerateArray())
????????????{
????????????????list.Add(Obtain(item));
????????????}
????????????return?list;
????????}
????????//?Undefine、Object
????????else?return?new?JTextAccessor(element);
????}
}
編寫一個(gè)Controller來驗(yàn)證
[HttpPost]
public?IActionResult?Post([FromBody]?dynamic?value)
{
????dynamic?ja?=?new?JTextAccessor(value);
????string?Name?=?ja.Name;
????int?Age?=?(int)ja.Age;
????var?list?=?ja.List;
????string?childName?=?list[0].Name;
????string?str?=?JsonSerializer.Serialize(value);
????_logger.LogInformation(str);
????return?Ok(new
??????????????{
??????????????????code?=?"0",
??????????????????message?=?"成功",
??????????????????reqCode?=?""
??????????????});
}
設(shè)置好斷點(diǎn),調(diào)試
調(diào)試斷點(diǎn)

使用postman做請(qǐng)求測試

查看調(diào)試的結(jié)果非常理想,成功偷懶省了事

一些推薦
【開源Blazor控件庫】Ant Design Blazor、Bootstrap風(fēng)格
【開源B/S項(xiàng)目】WTM
【開源WPF控件庫】MaterialDesignInXAML、MaterialDesignExtensions、Panuon.UI.Silver、HandyControl、AduSkin-UI、ModernWpf
【開源WPF項(xiàng)目】Accelerider.Windows、TerminalMACS.ManagerForWPF
【開源Xamarin項(xiàng)目】全球優(yōu)秀Xamarin.Forms項(xiàng)目收集
【開源Winform控件庫】HZHControls、SunnyUI】
【開源Winform項(xiàng)目】SiMay遠(yuǎn)程控制管理系統(tǒng)
【開源Qt控件庫】QWidgetDemo、Material風(fēng)格的Qt控件
【開源Qt項(xiàng)目】開源Android實(shí)時(shí)投屏軟件
?時(shí)間如流水,只能流去不流回。
公眾號(hào):Dotnet9 作者:非法關(guān)鍵字 原文:【C# Dynamic與Newtonsoft.Json的應(yīng)用、C# 通過Dynamic訪問System.Text.Json對(duì)象】 編輯:沙漠之盡頭的狼 日期:2020-12-02 微信公眾號(hào):Dotnet9
點(diǎn)擊閱讀原文,關(guān)注Dotnet9更多好文。
