溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C#中怎么利用表達(dá)式綁定數(shù)據(jù)

發(fā)布時(shí)間:2021-07-07 15:13:56 來(lái)源:億速云 閱讀:156 作者:Leah 欄目:大數(shù)據(jù)

C#中怎么利用表達(dá)式綁定數(shù)據(jù),針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

首先,數(shù)據(jù)類(lèi)還是要對(duì)每條屬性寫(xiě)存取器,語(yǔ)言特性限制沒(méi)辦法。不過(guò)有模板也不算麻煩吧。

public class A:BindAble{    private int _a;    public int a { get => GetProperty(ref _a); set => SetProperty(ref _a, value); }
   private int _b;    public int b { get => GetProperty(ref _b); set => SetProperty(ref _b, value); }}

比較合理的方法是用元標(biāo)簽標(biāo)記屬性

[BindAble]public int a;[BindAble]public int b;

但想要實(shí)現(xiàn)它,現(xiàn)實(shí)的做法就只能編譯生成代碼注入DLL(xLua的方法),也不是不能寫(xiě),但我這個(gè)只是個(gè)玩具就先放著吧。

綁定數(shù)據(jù)的時(shí)候需要new一個(gè)BindHandler出來(lái),然后調(diào)用BindProperty,輸入setter和getter的Lambda表達(dá)式。語(yǔ)言特性下,不想反射只能這樣寫(xiě)。

new BindHandler().BindProperty(v => obj2.a = v, () => obj.a);

這段代碼表示obj2.a的值會(huì)始終和obj.a保持相同。

取消綁定則調(diào)用BindHandler的UnBind方法。

如果想綁定至函數(shù)則是

new BindHandler().BindAction(e => xxxxxx).AddTarget(()=> obj.a);

AddTarget可多次調(diào)用。

如果綁定目標(biāo)是列表,同時(shí)希望列表內(nèi)元素變化時(shí)也有感知,則需要換用Collections目錄下包裝后的列表,這也是沒(méi)辦法的事情。

最后,既然是Lambda表達(dá)式,getter那邊是可以寫(xiě)成多個(gè)參數(shù)的,即:

new BindHandler().BindProperty(v => obj3.a = v, () => obj.a + obj2.a);

這樣obj3.a的值會(huì)始終等于obj.a和obj2.a的和,后面兩個(gè)值任意一個(gè)變化,obj3.a都會(huì)更新一次。

雙向綁定,限于條件只能寫(xiě)兩條BindHandler了,因?yàn)橛信兄夭⒉粫?huì)無(wú)限觸發(fā)。

new BindHandler().BindProperty(v => obj2.a = v, () => obj.a);new BindHandler().BindProperty(v => obj.a = v, () => obj2.a);


基本綁定的實(shí)現(xiàn)很顯然就是改寫(xiě)setter然后觸發(fā)event,然后監(jiān)聽(tīng)后給另一個(gè)數(shù)賦值,并沒(méi)有什么可說(shuō)的。這個(gè)實(shí)現(xiàn)比較有趣的地方是輸入表達(dá)式就能自動(dòng)綁定表達(dá)式內(nèi)的多個(gè)數(shù)據(jù),普通的做法怎么想都需要一個(gè)一個(gè)AddTarget。

實(shí)現(xiàn)這個(gè)一般的想法是用C#的Expression,解析Lambda表達(dá)式獲取需要綁定的屬性然后加監(jiān)聽(tīng)。我一開(kāi)始想用這個(gè)的,但Expression很有可能因?yàn)樯婕癑IT被IOS打回來(lái),猶豫了很久。但如果沒(méi)有這個(gè)功能,綁定就繞不開(kāi)輸入字符串形式的屬性名,就又會(huì)陷入“拼寫(xiě)錯(cuò)誤”“重構(gòu)失效”之類(lèi)的隱患里,對(duì)我來(lái)講就失去了使用價(jià)值。

好在后來(lái)找到了另一個(gè)方法來(lái)實(shí)現(xiàn)。這個(gè)方法非常的騷,如果直接看我的代碼可能會(huì)反應(yīng)不過(guò)來(lái)。專(zhuān)門(mén)解釋下吧。

我在BindHandler里加監(jiān)聽(tīng)的代碼是這樣的:

internal static BindHandler recordingBindHandler = null;void AddExpressionListener<T>(Func<T> expression){      recordingBindHandler = this;      expression.Invoke();      recordingBindHandler = null;}

僅僅是把Handler暫時(shí)放在一個(gè)靜態(tài)字段上,然后調(diào)用了一下綁定目標(biāo)的expression。

看起來(lái)什么都沒(méi)做?但調(diào)用expression的時(shí)候,實(shí)際上是會(huì)觸發(fā)里面涉及到的屬性的getter的……

而那些屬性的getter長(zhǎng)這樣:

protected T GetProperty<T>(ref T property, [CallerMemberName]string propertyName = null){     if (BindHandler.recordingBindHandler != null)     {          BindHandler.recordingBindHandler.AddTarget(this, propertyName);     }     return property;}

便通過(guò)這樣的一次反向注冊(cè)實(shí)現(xiàn)了需求。

當(dāng)然,這個(gè)和直接用Expression肯定不一樣,比如只要里面有&&一類(lèi)會(huì)導(dǎo)致中斷的運(yùn)算符,后面的部分就可能調(diào)用不到導(dǎo)致沒(méi)有注冊(cè)。所以用的時(shí)候得注意點(diǎn)。

大部分情況應(yīng)該都沒(méi)問(wèn)題。


這玩意兒看起來(lái)很高級(jí),但實(shí)現(xiàn)需要的代碼量卻很少,我自己都很吃驚。實(shí)現(xiàn)后續(xù)特性的時(shí)候發(fā)現(xiàn)竟然只有加幾行就可以,想著不可能這樣就行了吧,跑了測(cè)試卻發(fā)現(xiàn)竟然對(duì)了。

所以不管怎么說(shuō)還是挺開(kāi)心的。

其實(shí)還可以考慮搞成:

new BindHandler().BindProperty(() => obj2.a = obj.a);

這樣就更直觀了,但就怕有人會(huì)寫(xiě)成這樣

new BindHandler().BindProperty(() => p.obj2.a = obj.a);

關(guān)于C#中怎么利用表達(dá)式綁定數(shù)據(jù)問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI