我们大使用Delegate时,需要考虑其反注册操作。写代码以下几个问题,总会造成困扰。
1. 反注册很爱忘记
2. 有时也不好进行反注册,比如使用Lambda给一个委托赋值时。所以Unity也是考虑这个原因,才使用UnityEvent吧(这个也得自己反注册)。
3. 有时不知道向谁反注册。比如,向一个局部变量的委托进行注册,如果再想反注册就得再加一个其成员变量,加重了代码的偶合度。
这里介绍一下,使用UniRX的思想,把Delegate转为Observable,这个反注册可以进行。还可以与其它RX的组件配合使用,很方便。其实RX的思想就是要统一的事件处理。
看了一些UniRX的组件,FromEvent最合适做这个事了,但其参数比较复杂。只是看代码不好理解其参数的含义,网上相关的资料也比较少。
public delegate void OnClose();
public delegate void OnCloseArg(int a);
close = Observable.FromEvent<OnClose>(h => ()=> h(), h => test += h, h => test -= h).Subscribe(_=> Debug.Log("On close"));
Observable.FromEvent<OnCloseArg, int>(h => a => h(a), h => testArg += h, h => testArg -= h).Subscribe(_ => Debug.Log("On close Arg" + _));
第二、三参数比较好理解了就是完成真正的向委托注册、反注册的工作。第一个参数比较不好理解,我是从以下源码发现的线索。其是要OnNext转换为委托可以接入的方法,就封装一层,而OnNext就是我们要在Subscribe中定义的处理函数。
public bool Register()
{
handler = parent.conversion(OnNext);
try
{
parent.addHandler(handler);
}
catch (Exception ex)
{
observer.OnError(ex);
return false;
}
return true;
}
void OnNext()
{
observer.OnNext(Unit.Default);
}
由于代码比较长本想写个共通代码
public static class DelegateObservable
{
static public IObservable<Unit> Action(Action action)
{
return Observable.FromEvent<Action>(h => () => h(), h => action += h, h => action -= h);
}
static public IObservable<T> Action<T>(ref Action<T> action)
{
var action2 = action;
return Observable.FromEvent<Action<T>, T>(h => (a) => h(a), h => action2 += h, h => action2 -= h);
}
}
但委托这东西是个值类型,传入ref,还说在lambda中无法访问。有高人有好方法,可以给回复。
其中UnityEvent也可以变换为RX
static public IObservable<Unit> OnUnityEvent(UnityEvent uEvent)
{
return Observable.FromEvent<UnityAction>(h => ()=>h(), h => uEvent.AddListener(h), h => uEvent.RemoveListener(h));
}