两种方法都可以实现对对象中数据的绑定,第一种通过接口实现,第二种通过委托实现,都需要手动添加绑定,第一种手动触发对应事件,第二种自动触发对应事件。
一、通过接口实现
1.首先定义需要触发的事件的接口
public interface IWBindable
{
void onBindingUpdate(Wbindable vo);
}
2.定义值对象的基类,实现事件的注册注销等
public class Wbindable
{
private List<IWBindable> m_listCallBacks = new List<IWBindable>();
public bool hasBinding(IWBindable receiver)
{
foreach (IWBindable wkr in m_listCallBacks)
{
if (wkr == receiver)
{
return true;
}
}
return false;
}
public void addBinding(IWBindable receiver)
{
if (hasBinding(receiver))
{
return;
}
m_listCallBacks.Add(receiver);
}
public void removeBinding(IWBindable receiver)
{
List<IWBindable> l = new List<IWBindable>(m_listCallBacks);
foreach (IWBindable wkr in l)
{
if (wkr == null || wkr == receiver)
{
m_listCallBacks.Remove(wkr);
}
}
}
public void notifyBindings()
{
List<IWBindable> l = new List<IWBindable>(m_listCallBacks);
foreach (IWBindable wkr in l)
{
if (wkr == null)
{
m_listCallBacks.Remove(wkr);
}
else
{
wkr.onBindingUpdate(this);
}
}
}
}
3.测试代码跑起来,创建一个具体的值对象类,实例化出来后通过notifyBindings方法可以获取该类实例的当前字段的值,而onBindingUpdate方法中决定你想监听哪个值或者触发一些其他的事件。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemWbindable : Wbindable
{
public string name;
public int Id;
}
public class BindTest : MonoBehaviour, IWBindable
{
// Use this for initialization
void Start()
{
ItemWbindable vo = new ItemWbindable();
vo.name = "aaa";
vo.Id = 1;
vo.addBinding(this);
vo.notifyBindings();
}
public void onBindingUpdate(Wbindable vo)
{
ItemWbindable m_vo = (ItemWbindable)vo;
Debug.Log(string.Format("变化后的值:{0}----{1}", m_vo.name, m_vo.Id));
//监听对象的值的变化or do sthing
}
}
二、通过委托实现
1.同样的实现值对象基类,注册注销等方法
public class Model {
private Type m_thisType;
public delegate void BindingDataDelegate(object objData);
private Dictionary<string, List<BindingDataDelegate>> m_dicDataBinding = new Dictionary<string, List<BindingDataDelegate>>();
public Model()
{
m_thisType = GetType();
}
public void addDataBinding(BindingDataDelegate callBack, string propertyName)
{
List<BindingDataDelegate> methods = null;
if (m_dicDataBinding.ContainsKey(propertyName))
{
methods = m_dicDataBinding[propertyName];
}
else
{
methods = new List<BindingDataDelegate>();
m_dicDataBinding.Add(propertyName, methods);
}
methods.Add(callBack);
}
public void updateBinding(string propertyName)
{
if (m_dicDataBinding.ContainsKey(propertyName))
{
//Dictionary<string, List<BindingDataDelegate>> allBindings = new Dictionary<string, List<BindingDataDelegate>>(m_dicDataBinding);
object objData = _getPropertyValue(propertyName);
List<BindingDataDelegate> bds = new List<BindingDataDelegate>(m_dicDataBinding[propertyName]);
foreach (BindingDataDelegate m in bds)
{
m(objData);
}
}
}
public void updateBinding(string propertyName, object customParam)
{
if (m_dicDataBinding.ContainsKey(propertyName))
{
List<BindingDataDelegate> bds = new List<BindingDataDelegate>(m_dicDataBinding[propertyName]);
foreach (BindingDataDelegate m in bds)
{
m(customParam);
}
}
}
public void removeDataBinding(BindingDataDelegate callBack, string propertyName)
{
List<BindingDataDelegate> methods = null;
if (m_dicDataBinding.ContainsKey(propertyName))
{
methods = m_dicDataBinding[propertyName];
if (methods.Contains(callBack))
{
methods.Remove(callBack);
}
}
}
private object _getPropertyValue(string strName)
{
object value = null;
FieldInfo fi = m_thisType.GetField(strName);
if (fi != null)
{
value = fi.GetValue(this);
}
else
{
//PropertyInfo pi=m_thisType.GetProperty(strName);
value = this.GetType().GetProperty(strName).GetValue(this, null);
}
return value;
}
}
2.值对象具体类
public class ItemModel : Model {
string str;
public string Str
{
get { return str; }
set { str = value; updateBinding("Str"); }
}
}
3.测试代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
using System;
public class DataBindTest : MonoBehaviour {
void Start () {
ItemModel model = new ItemModel();
model.addDataBinding(fun, "Str");
model.Str = "新的值";
}
void fun(object para) {
Debug.Log(para);
//do sthing
}
}