PageRenderTime 82ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/ReactiveUI/VariadicTemplates_WP7.cs

https://github.com/bsiegel/ReactiveUI
C# | 324 lines | 237 code | 31 blank | 56 comment | 4 complexity | cae7e2fa99fa66495613d98a2f82e270 MD5 | raw file
Possible License(s): Apache-2.0, CC-BY-SA-3.0, LGPL-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reactive.Disposables;
  4. using System.Reactive.Linq;
  5. using System.Diagnostics.Contracts;
  6. using System.Linq;
  7. using System.Linq.Expressions;
  8. using System.Reflection;
  9. using System.Text;
  10. namespace ReactiveUI
  11. {
  12. public static class WhenAnyMixin
  13. {
  14. /// <summary>
  15. /// WhenAny allows you to observe whenever one or more properties on an
  16. /// object have changed, providing an initial value when the Observable
  17. /// is set up, unlike ObservableForProperty(). Use this method in
  18. /// constructors to set up bindings between properties that also need an
  19. /// initial setup.
  20. /// </summary>
  21. public static IObservable<TRet> WhenAny<TSender, TRet, T1>(this TSender This,
  22. Expression<Func<TSender, T1>> property1,
  23. Func<IObservedChange<TSender, T1>, TRet> selector)
  24. {
  25. bool allInputsWorked = true;
  26. var slot1 = new ObservedChange<TSender, T1>() {
  27. Sender = This,
  28. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property1)),
  29. };
  30. T1 slot1Value = default(T1); allInputsWorked &= slot1.TryGetValue(out slot1Value); slot1.Value = slot1Value;
  31. IObservedChange<TSender, T1> islot1 = slot1;
  32. return Observable.Create<TRet>(subject => {
  33. if (allInputsWorked) subject.OnNext(selector(islot1));
  34. return Observable.Merge(
  35. This.ObservableForProperty(property1).Do(x => { lock (slot1) { islot1 = x.fillInValue(); } }).Select(x => selector(islot1))
  36. ).Subscribe(subject);
  37. });
  38. }
  39. /// <summary>
  40. /// WhenAny allows you to observe whenever one or more properties on an
  41. /// object have changed, providing an initial value when the Observable
  42. /// is set up, unlike ObservableForProperty(). Use this method in
  43. /// constructors to set up bindings between properties that also need an
  44. /// initial setup.
  45. /// </summary>
  46. public static IObservable<TRet> WhenAnyDynamic<TSender, TRet>(this TSender This,
  47. string[] property1,
  48. Func<IObservedChange<TSender, object>, TRet> selector)
  49. {
  50. var slot1 = new ObservedChange<TSender, object>() {
  51. Sender = This,
  52. PropertyName = String.Join(".", property1),
  53. };
  54. object slot1Value = default(object); slot1.TryGetValue(out slot1Value); slot1.Value = slot1Value;
  55. IObservedChange<TSender, object> islot1 = slot1;
  56. return Observable.Create<TRet>(subject => {
  57. subject.OnNext(selector(islot1));
  58. return Observable.Merge( This.ObservableForProperty(property1).Do(x => { lock (slot1) { islot1 = x.fillInValue(); } }).Select(x => selector(islot1)) ).Subscribe(subject);
  59. });
  60. }
  61. /// <summary>
  62. /// WhenAny allows you to observe whenever one or more properties on an
  63. /// object have changed, providing an initial value when the Observable
  64. /// is set up, unlike ObservableForProperty(). Use this method in
  65. /// constructors to set up bindings between properties that also need an
  66. /// initial setup.
  67. /// </summary>
  68. public static IObservable<TRet> WhenAny<TSender, TRet, T1,T2>(this TSender This,
  69. Expression<Func<TSender, T1>> property1,
  70. Expression<Func<TSender, T2>> property2,
  71. Func<IObservedChange<TSender, T1>, IObservedChange<TSender, T2>, TRet> selector)
  72. {
  73. bool allInputsWorked = true;
  74. var slot1 = new ObservedChange<TSender, T1>() {
  75. Sender = This,
  76. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property1)),
  77. };
  78. T1 slot1Value = default(T1); allInputsWorked &= slot1.TryGetValue(out slot1Value); slot1.Value = slot1Value;
  79. IObservedChange<TSender, T1> islot1 = slot1;
  80. var slot2 = new ObservedChange<TSender, T2>() {
  81. Sender = This,
  82. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property2)),
  83. };
  84. T2 slot2Value = default(T2); allInputsWorked &= slot2.TryGetValue(out slot2Value); slot2.Value = slot2Value;
  85. IObservedChange<TSender, T2> islot2 = slot2;
  86. return Observable.Create<TRet>(subject => {
  87. if (allInputsWorked) subject.OnNext(selector(islot1, islot2));
  88. return Observable.Merge(
  89. This.ObservableForProperty(property1).Do(x => { lock (slot1) { islot1 = x.fillInValue(); } }).Select(x => selector(islot1, islot2)),
  90. This.ObservableForProperty(property2).Do(x => { lock (slot2) { islot2 = x.fillInValue(); } }).Select(x => selector(islot1, islot2))
  91. ).Subscribe(subject);
  92. });
  93. }
  94. /// <summary>
  95. /// WhenAny allows you to observe whenever one or more properties on an
  96. /// object have changed, providing an initial value when the Observable
  97. /// is set up, unlike ObservableForProperty(). Use this method in
  98. /// constructors to set up bindings between properties that also need an
  99. /// initial setup.
  100. /// </summary>
  101. public static IObservable<TRet> WhenAnyDynamic<TSender, TRet>(this TSender This,
  102. string[] property1,
  103. string[] property2,
  104. Func<IObservedChange<TSender, object>, IObservedChange<TSender, object>, TRet> selector)
  105. {
  106. var slot1 = new ObservedChange<TSender, object>() {
  107. Sender = This,
  108. PropertyName = String.Join(".", property1),
  109. };
  110. object slot1Value = default(object); slot1.TryGetValue(out slot1Value); slot1.Value = slot1Value;
  111. IObservedChange<TSender, object> islot1 = slot1;
  112. var slot2 = new ObservedChange<TSender, object>() {
  113. Sender = This,
  114. PropertyName = String.Join(".", property2),
  115. };
  116. object slot2Value = default(object); slot2.TryGetValue(out slot2Value); slot2.Value = slot2Value;
  117. IObservedChange<TSender, object> islot2 = slot2;
  118. return Observable.Create<TRet>(subject => {
  119. subject.OnNext(selector(islot1, islot2));
  120. return Observable.Merge( This.ObservableForProperty(property1).Do(x => { lock (slot1) { islot1 = x.fillInValue(); } }).Select(x => selector(islot1, islot2)), This.ObservableForProperty(property2).Do(x => { lock (slot2) { islot2 = x.fillInValue(); } }).Select(x => selector(islot1, islot2)) ).Subscribe(subject);
  121. });
  122. }
  123. /// <summary>
  124. /// WhenAny allows you to observe whenever one or more properties on an
  125. /// object have changed, providing an initial value when the Observable
  126. /// is set up, unlike ObservableForProperty(). Use this method in
  127. /// constructors to set up bindings between properties that also need an
  128. /// initial setup.
  129. /// </summary>
  130. public static IObservable<TRet> WhenAny<TSender, TRet, T1,T2,T3>(this TSender This,
  131. Expression<Func<TSender, T1>> property1,
  132. Expression<Func<TSender, T2>> property2,
  133. Expression<Func<TSender, T3>> property3,
  134. Func<IObservedChange<TSender, T1>, IObservedChange<TSender, T2>, IObservedChange<TSender, T3>, TRet> selector)
  135. {
  136. bool allInputsWorked = true;
  137. var slot1 = new ObservedChange<TSender, T1>() {
  138. Sender = This,
  139. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property1)),
  140. };
  141. T1 slot1Value = default(T1); allInputsWorked &= slot1.TryGetValue(out slot1Value); slot1.Value = slot1Value;
  142. IObservedChange<TSender, T1> islot1 = slot1;
  143. var slot2 = new ObservedChange<TSender, T2>() {
  144. Sender = This,
  145. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property2)),
  146. };
  147. T2 slot2Value = default(T2); allInputsWorked &= slot2.TryGetValue(out slot2Value); slot2.Value = slot2Value;
  148. IObservedChange<TSender, T2> islot2 = slot2;
  149. var slot3 = new ObservedChange<TSender, T3>() {
  150. Sender = This,
  151. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property3)),
  152. };
  153. T3 slot3Value = default(T3); allInputsWorked &= slot3.TryGetValue(out slot3Value); slot3.Value = slot3Value;
  154. IObservedChange<TSender, T3> islot3 = slot3;
  155. return Observable.Create<TRet>(subject => {
  156. if (allInputsWorked) subject.OnNext(selector(islot1, islot2, islot3));
  157. return Observable.Merge(
  158. This.ObservableForProperty(property1).Do(x => { lock (slot1) { islot1 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3)),
  159. This.ObservableForProperty(property2).Do(x => { lock (slot2) { islot2 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3)),
  160. This.ObservableForProperty(property3).Do(x => { lock (slot3) { islot3 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3))
  161. ).Subscribe(subject);
  162. });
  163. }
  164. /// <summary>
  165. /// WhenAny allows you to observe whenever one or more properties on an
  166. /// object have changed, providing an initial value when the Observable
  167. /// is set up, unlike ObservableForProperty(). Use this method in
  168. /// constructors to set up bindings between properties that also need an
  169. /// initial setup.
  170. /// </summary>
  171. public static IObservable<TRet> WhenAnyDynamic<TSender, TRet>(this TSender This,
  172. string[] property1,
  173. string[] property2,
  174. string[] property3,
  175. Func<IObservedChange<TSender, object>, IObservedChange<TSender, object>, IObservedChange<TSender, object>, TRet> selector)
  176. {
  177. var slot1 = new ObservedChange<TSender, object>() {
  178. Sender = This,
  179. PropertyName = String.Join(".", property1),
  180. };
  181. object slot1Value = default(object); slot1.TryGetValue(out slot1Value); slot1.Value = slot1Value;
  182. IObservedChange<TSender, object> islot1 = slot1;
  183. var slot2 = new ObservedChange<TSender, object>() {
  184. Sender = This,
  185. PropertyName = String.Join(".", property2),
  186. };
  187. object slot2Value = default(object); slot2.TryGetValue(out slot2Value); slot2.Value = slot2Value;
  188. IObservedChange<TSender, object> islot2 = slot2;
  189. var slot3 = new ObservedChange<TSender, object>() {
  190. Sender = This,
  191. PropertyName = String.Join(".", property3),
  192. };
  193. object slot3Value = default(object); slot3.TryGetValue(out slot3Value); slot3.Value = slot3Value;
  194. IObservedChange<TSender, object> islot3 = slot3;
  195. return Observable.Create<TRet>(subject => {
  196. subject.OnNext(selector(islot1, islot2, islot3));
  197. return Observable.Merge( This.ObservableForProperty(property1).Do(x => { lock (slot1) { islot1 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3)), This.ObservableForProperty(property2).Do(x => { lock (slot2) { islot2 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3)), This.ObservableForProperty(property3).Do(x => { lock (slot3) { islot3 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3)) ).Subscribe(subject);
  198. });
  199. }
  200. /// <summary>
  201. /// WhenAny allows you to observe whenever one or more properties on an
  202. /// object have changed, providing an initial value when the Observable
  203. /// is set up, unlike ObservableForProperty(). Use this method in
  204. /// constructors to set up bindings between properties that also need an
  205. /// initial setup.
  206. /// </summary>
  207. public static IObservable<TRet> WhenAny<TSender, TRet, T1,T2,T3,T4>(this TSender This,
  208. Expression<Func<TSender, T1>> property1,
  209. Expression<Func<TSender, T2>> property2,
  210. Expression<Func<TSender, T3>> property3,
  211. Expression<Func<TSender, T4>> property4,
  212. Func<IObservedChange<TSender, T1>, IObservedChange<TSender, T2>, IObservedChange<TSender, T3>, IObservedChange<TSender, T4>, TRet> selector)
  213. {
  214. bool allInputsWorked = true;
  215. var slot1 = new ObservedChange<TSender, T1>() {
  216. Sender = This,
  217. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property1)),
  218. };
  219. T1 slot1Value = default(T1); allInputsWorked &= slot1.TryGetValue(out slot1Value); slot1.Value = slot1Value;
  220. IObservedChange<TSender, T1> islot1 = slot1;
  221. var slot2 = new ObservedChange<TSender, T2>() {
  222. Sender = This,
  223. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property2)),
  224. };
  225. T2 slot2Value = default(T2); allInputsWorked &= slot2.TryGetValue(out slot2Value); slot2.Value = slot2Value;
  226. IObservedChange<TSender, T2> islot2 = slot2;
  227. var slot3 = new ObservedChange<TSender, T3>() {
  228. Sender = This,
  229. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property3)),
  230. };
  231. T3 slot3Value = default(T3); allInputsWorked &= slot3.TryGetValue(out slot3Value); slot3.Value = slot3Value;
  232. IObservedChange<TSender, T3> islot3 = slot3;
  233. var slot4 = new ObservedChange<TSender, T4>() {
  234. Sender = This,
  235. PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property4)),
  236. };
  237. T4 slot4Value = default(T4); allInputsWorked &= slot4.TryGetValue(out slot4Value); slot4.Value = slot4Value;
  238. IObservedChange<TSender, T4> islot4 = slot4;
  239. return Observable.Create<TRet>(subject => {
  240. if (allInputsWorked) subject.OnNext(selector(islot1, islot2, islot3, islot4));
  241. return Observable.Merge(
  242. This.ObservableForProperty(property1).Do(x => { lock (slot1) { islot1 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3, islot4)),
  243. This.ObservableForProperty(property2).Do(x => { lock (slot2) { islot2 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3, islot4)),
  244. This.ObservableForProperty(property3).Do(x => { lock (slot3) { islot3 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3, islot4)),
  245. This.ObservableForProperty(property4).Do(x => { lock (slot4) { islot4 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3, islot4))
  246. ).Subscribe(subject);
  247. });
  248. }
  249. /// <summary>
  250. /// WhenAny allows you to observe whenever one or more properties on an
  251. /// object have changed, providing an initial value when the Observable
  252. /// is set up, unlike ObservableForProperty(). Use this method in
  253. /// constructors to set up bindings between properties that also need an
  254. /// initial setup.
  255. /// </summary>
  256. public static IObservable<TRet> WhenAnyDynamic<TSender, TRet>(this TSender This,
  257. string[] property1,
  258. string[] property2,
  259. string[] property3,
  260. string[] property4,
  261. Func<IObservedChange<TSender, object>, IObservedChange<TSender, object>, IObservedChange<TSender, object>, IObservedChange<TSender, object>, TRet> selector)
  262. {
  263. var slot1 = new ObservedChange<TSender, object>() {
  264. Sender = This,
  265. PropertyName = String.Join(".", property1),
  266. };
  267. object slot1Value = default(object); slot1.TryGetValue(out slot1Value); slot1.Value = slot1Value;
  268. IObservedChange<TSender, object> islot1 = slot1;
  269. var slot2 = new ObservedChange<TSender, object>() {
  270. Sender = This,
  271. PropertyName = String.Join(".", property2),
  272. };
  273. object slot2Value = default(object); slot2.TryGetValue(out slot2Value); slot2.Value = slot2Value;
  274. IObservedChange<TSender, object> islot2 = slot2;
  275. var slot3 = new ObservedChange<TSender, object>() {
  276. Sender = This,
  277. PropertyName = String.Join(".", property3),
  278. };
  279. object slot3Value = default(object); slot3.TryGetValue(out slot3Value); slot3.Value = slot3Value;
  280. IObservedChange<TSender, object> islot3 = slot3;
  281. var slot4 = new ObservedChange<TSender, object>() {
  282. Sender = This,
  283. PropertyName = String.Join(".", property4),
  284. };
  285. object slot4Value = default(object); slot4.TryGetValue(out slot4Value); slot4.Value = slot4Value;
  286. IObservedChange<TSender, object> islot4 = slot4;
  287. return Observable.Create<TRet>(subject => {
  288. subject.OnNext(selector(islot1, islot2, islot3, islot4));
  289. return Observable.Merge( This.ObservableForProperty(property1).Do(x => { lock (slot1) { islot1 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3, islot4)), This.ObservableForProperty(property2).Do(x => { lock (slot2) { islot2 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3, islot4)), This.ObservableForProperty(property3).Do(x => { lock (slot3) { islot3 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3, islot4)), This.ObservableForProperty(property4).Do(x => { lock (slot4) { islot4 = x.fillInValue(); } }).Select(x => selector(islot1, islot2, islot3, islot4)) ).Subscribe(subject);
  290. });
  291. }
  292. }
  293. }