重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
C#中怎么利用表达式绑定数据,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站设计、成都网站建设、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的浠水网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
首先,数据类还是要对每条属性写存取器,语言特性限制没办法。不过有模板也不算麻烦吧。
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); }
}
比较合理的方法是用元标签标记属性
[BindAble]public int a;[BindAble]public int b;
但想要实现它,现实的做法就只能编译生成代码注入DLL(xLua的方法),也不是不能写,但我这个只是个玩具就先放着吧。
绑定数据的时候需要new一个BindHandler出来,然后调用BindProperty,输入setter和getter的Lambda表达式。语言特性下,不想反射只能这样写。
new BindHandler().BindProperty(v => obj2.a = v, () => obj.a);
这段代码表示obj2.a的值会始终和obj.a保持相同。
取消绑定则调用BindHandler的UnBind方法。
如果想绑定至函数则是
new BindHandler().BindAction(e => xxxxxx).AddTarget(()=> obj.a);
AddTarget可多次调用。
如果绑定目标是列表,同时希望列表内元素变化时也有感知,则需要换用Collections目录下包装后的列表,这也是没办法的事情。
最后,既然是Lambda表达式,getter那边是可以写成多个参数的,即:
new BindHandler().BindProperty(v => obj3.a = v, () => obj.a + obj2.a);
这样obj3.a的值会始终等于obj.a和obj2.a的和,后面两个值任意一个变化,obj3.a都会更新一次。
双向绑定,限于条件只能写两条BindHandler了,因为有判重并不会无限触发。
new BindHandler().BindProperty(v => obj2.a = v, () => obj.a);new BindHandler().BindProperty(v => obj.a = v, () => obj2.a);
基本绑定的实现很显然就是改写setter然后触发event,然后监听后给另一个数赋值,并没有什么可说的。这个实现比较有趣的地方是输入表达式就能自动绑定表达式内的多个数据,普通的做法怎么想都需要一个一个AddTarget。
实现这个一般的想法是用C#的Expression,解析Lambda表达式获取需要绑定的属性然后加监听。我一开始想用这个的,但Expression很有可能因为涉及JIT被IOS打回来,犹豫了很久。但如果没有这个功能,绑定就绕不开输入字符串形式的属性名,就又会陷入“拼写错误”“重构失效”之类的隐患里,对我来讲就失去了使用价值。
好在后来找到了另一个方法来实现。这个方法非常的骚,如果直接看我的代码可能会反应不过来。专门解释下吧。
我在BindHandler里加监听的代码是这样的:
internal static BindHandler recordingBindHandler = null;void AddExpressionListener(Func expression){ recordingBindHandler = this; expression.Invoke(); recordingBindHandler = null;}
仅仅是把Handler暂时放在一个静态字段上,然后调用了一下绑定目标的expression。
看起来什么都没做?但调用expression的时候,实际上是会触发里面涉及到的属性的getter的……
而那些属性的getter长这样:
protected T GetProperty(ref T property, [CallerMemberName]string propertyName = null){ if (BindHandler.recordingBindHandler != null) { BindHandler.recordingBindHandler.AddTarget(this, propertyName); } return property;}
便通过这样的一次反向注册实现了需求。
当然,这个和直接用Expression肯定不一样,比如只要里面有&&一类会导致中断的运算符,后面的部分就可能调用不到导致没有注册。所以用的时候得注意点。
大部分情况应该都没问题。
这玩意儿看起来很高级,但实现需要的代码量却很少,我自己都很吃惊。实现后续特性的时候发现竟然只有加几行就可以,想着不可能这样就行了吧,跑了测试却发现竟然对了。
所以不管怎么说还是挺开心的。
其实还可以考虑搞成:
new BindHandler().BindProperty(() => obj2.a = obj.a);
这样就更直观了,但就怕有人会写成这样
new BindHandler().BindProperty(() => p.obj2.a = obj.a);
关于C#中怎么利用表达式绑定数据问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。