8
8
//
9
9
// ********************************************************************
10
10
11
+ // ReSharper disable CheckNamespace
12
+
11
13
using System ;
12
14
using UnityEngine ;
13
15
@@ -18,9 +20,13 @@ namespace RimuruDev
18
20
public class ReactiveProperty < T >
19
21
{
20
22
[ SerializeField ] private T value ;
21
-
22
23
[ NonSerialized ] private Action < T > onChanged ;
23
24
25
+ public ReactiveProperty ( T initialValue = default )
26
+ {
27
+ value = initialValue ;
28
+ }
29
+
24
30
public event Action < T > OnChanged
25
31
{
26
32
add
@@ -46,9 +52,51 @@ public void OnNext(T nextValue)
46
52
Value = nextValue ;
47
53
}
48
54
49
- public ReactiveProperty ( T initialValue = default )
55
+ /// <summary>
56
+ /// Подписка на изменения с поддержкой IDisposable.
57
+ /// <example>
58
+ /// <code>
59
+ /// Пример:
60
+ /// 1:
61
+ /// private readonly List-IDisposable> subscriptions = new();
62
+ ///
63
+ /// 2:
64
+ /// subscriptions.Add(UserName.Subscribe(value => Origin.UserName = value));
65
+ ///
66
+ /// 3:
67
+ /// foreach (var subscription in subscriptions)
68
+ /// subscription.Dispose();
69
+ /// </code>
70
+ /// </example>
71
+ /// </summary>
72
+ /// <param name="callback">Метод обратного вызова.</param>
73
+ /// <returns>Объект IDisposable для отписки.</returns>
74
+ public IDisposable Subscribe ( Action < T > callback )
50
75
{
51
- value = initialValue ;
76
+ OnChanged += callback ;
77
+
78
+ // NOTE: Возвращаем объект, который при Dispose выполнит отписку.
79
+ return new DisposableAction ( ( ) => OnChanged -= callback ) ;
80
+ }
81
+
82
+ private class DisposableAction : IDisposable
83
+ {
84
+ private readonly Action disposeAction ;
85
+ private bool isDisposed ;
86
+
87
+ public DisposableAction ( Action disposeAction )
88
+ {
89
+ this . disposeAction = disposeAction ;
90
+ }
91
+
92
+ public void Dispose ( )
93
+ {
94
+ if ( ! isDisposed )
95
+ {
96
+ disposeAction ? . Invoke ( ) ;
97
+ isDisposed = true ;
98
+ }
99
+ }
52
100
}
53
101
}
54
102
}
0 commit comments