-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
VariadicTemplates_WP7.tt
101 lines (88 loc) · 4.36 KB
/
VariadicTemplates_WP7.tt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core.dll" #>
<#@ import namespace="System.Linq" #>
<#@ output extension=".cs" #>
using System;
using System.Collections.Generic;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
<#
// NB: maxFuncLength is 4 on WP7, 12 on every other platform.
// VariadicTemplates_WP7.tt should always be a copy of VariadicTemplates.tt
// except for this section
int maxFuncLength = 4;
#>
namespace ReactiveUI
{
public static class WhenAnyMixin
{
<# for(int length=1; length <= maxFuncLength; length++) { #>
<# var templParams = Enumerable.Range(1, length).Select(x => "T" + x.ToString()); #>
<# string selectorTypeParams = String.Join(", ", templParams.Select(x => String.Format("IObservedChange<TSender, {0}>", x))); #>
<# string dynamicSelectorTypeParams = String.Join(", ", templParams.Select(x => "IObservedChange<TSender, object>")); #>
<# string selectorCall = "selector(" + String.Join(", ", Enumerable.Range(1, length).Select(x => "islot" + x.ToString())) + ")"; #>
/// <summary>
/// WhenAny allows you to observe whenever one or more properties on an
/// object have changed, providing an initial value when the Observable
/// is set up, unlike ObservableForProperty(). Use this method in
/// constructors to set up bindings between properties that also need an
/// initial setup.
/// </summary>
public static IObservable<TRet> WhenAny<TSender, TRet, <#= String.Join(",", templParams) #>>(this TSender This,
<# for(int i=1; i <= length; i++) { #>
Expression<Func<TSender, T<#=i#>>> property<#=i#>,
<# } #>
Func<<#= selectorTypeParams #>, TRet> selector)
{
bool allInputsWorked = true;
<# for(int i=1; i <= length; i++) { #>
var slot<#=i#> = new ObservedChange<TSender, T<#=i#>>() {
Sender = This,
PropertyName = String.Join(".", Reflection.ExpressionToPropertyNames(property<#=i#>)),
};
T<#=i#> slot<#=i#>Value = default(T<#=i#>); allInputsWorked &= slot<#=i#>.TryGetValue(out slot<#=i#>Value); slot<#=i#>.Value = slot<#=i#>Value;
IObservedChange<TSender, T<#=i#>> islot<#=i#> = slot<#=i#>;
<# } #>
return Observable.Create<TRet>(subject => {
if (allInputsWorked) subject.OnNext(<#= selectorCall #>);
return Observable.Merge(<# for(int i=1; i <= length; i++) { #>
This.ObservableForProperty(property<#=i#>).Do(x => { lock (slot<#=i#>) { islot<#=i#> = x.fillInValue(); } }).Select(x => <#= selectorCall #>)<#= (i==length?"":",") #> <# } #>
).Subscribe(subject);
});
}
/// <summary>
/// WhenAny allows you to observe whenever one or more properties on an
/// object have changed, providing an initial value when the Observable
/// is set up, unlike ObservableForProperty(). Use this method in
/// constructors to set up bindings between properties that also need an
/// initial setup.
/// </summary>
public static IObservable<TRet> WhenAnyDynamic<TSender, TRet>(this TSender This,
<# for(int i=1; i <= length; i++) { #>
string[] property<#=i#>,
<# } #>
Func<<#= dynamicSelectorTypeParams #>, TRet> selector)
{
<# for(int i=1; i <= length; i++) { #>
var slot<#=i#> = new ObservedChange<TSender, object>() {
Sender = This,
PropertyName = String.Join(".", property<#=i#>),
};
object slot<#=i#>Value = default(object); slot<#=i#>.TryGetValue(out slot<#=i#>Value); slot<#=i#>.Value = slot<#=i#>Value;
IObservedChange<TSender, object> islot<#=i#> = slot<#=i#>;
<# } #>
return Observable.Create<TRet>(subject => {
subject.OnNext(<#= selectorCall #>);
return Observable.Merge(<# for(int i=1; i <= length; i++) { #>
This.ObservableForProperty(property<#=i#>).Do(x => { lock (slot<#=i#>) { islot<#=i#> = x.fillInValue(); } }).Select(x => <#= selectorCall #>)<#= (i==length?"":",") #> <# } #>
).Subscribe(subject);
});
}
<# } #>
}
}