前言
笔者参与的项目的UI框架并没有采用MVC结构,而是把MVC中的C去掉了,只使用了MV,把C的逻辑拆分了一下,分别分为M里的C和V里的C,分别写在了对应的M或者V里面,V是根据M里的数据变化从而进行变化的。
问题
C#自带的属性并没有数据变化响应的事件或者委托,笔者的UI结构是需要根据数据变化进行更新的,所以笔者希望属性能有一个类似于OnValueChange的功能。
解决
方法一(使用委托)
这种方式是自己增加一个变量的委托事,然后在属性的set方法里进行响应对应的委托,每次需要监听数据变化的时候注册一下对应的委托就可以了。
缺点:变量需要定义成委托,并且每个需要监听变化的变量都需要增加一个委托的变量。
代码如下:
public class ExtendProperty
{
private int m_Value;
public Action<int, int> OnValueChange;
public int Value
{
get => m_Value;
set
{
OnValueChange?.Invoke(m_Value, value);
m_Value = value;
}
}
}
根据代码可以看出,如果是属性使用只需要两个变量,但是如果是字段使用就需要三个变量了。
使用方法如下:
void Start()
{
ExtendProperty property = new ExtendProperty();
property.Value = 10;
property.OnValueChange += OnValueChange;
property.Value = 20;
}
private void OnValueChange(int arg1, int arg2)
{
Debug.Log(string.Format("{0}-{1}", arg1, arg2));
}
方法二(推荐)
方法一的缺点很明显,如果是少数变量使用还可以,但是如果大量的变量都需要监听会比较麻烦,于是笔者就找到了另外的解决办法,笔者自定义一个类,然后变量都使用这个类定义,在类里面进行变量监听就可以了。
代码如下:
public class ExtendProperty<T>
{
private T m_Value;
public Action<T, T> OnValueChange;
public T Value
{
get => m_Value;
set
{
OnValueChange?.Invoke(m_Value, value);
m_Value = value;
}
}
public ExtendProperty(T value)
{
m_Value = value;
}
public ExtendProperty()
{
m_Value = default;
}
public static implicit operator T(ExtendProperty<T> vl)
{
return vl.Value;
}
}
缺点:定义普通变量的时候都需要初始化,不会默认赋值,并且每次使用变量的时候都不是直接赋值,而是采用property.Value = value的方式赋值。
使用案例如下:
ExtendProperty<int> property = new ExtendProperty<int>(10);
property.OnValueChange += OnValueChange;
property.Value = 20;
总结
采用OnValue的方式是一种简单的响应式框架,类似于UniRx,笔者在使用方法二的时候一直在想办法解决如何让使用者使用的时候像普通变量一样赋值而不是采用.Value的方式赋值,奈何一直找不到能拿到赋值的左值的方法。第二种方式更像是把第一种方式整合成一个对象,从而减少代码量。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 841774407@qq.com