#@ 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 = 12;
#>
namespace ReactiveUI
{
public static class WhenAnyMixin
{
///
/// WhenAnyValue allows you to observe whenever the value of a
/// property on an object has 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.
///
public static IObservable WhenAnyValue(this TSender This,
Expression> property1)
{
return This.WhenAny(property1, (IObservedChange c1) => c1.Value);
}
<# 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", x))); #>
<# string valuePropertyParams = String.Join(", ", Enumerable.Range(1, length).Select(x => String.Format("property{0}", x))); #>
<# string valueSelectorParams = String.Join(", ", Enumerable.Range(1, length).Select(x => "c" + x)); #>
<# string valueSelectorArgs = String.Join(", ", Enumerable.Range(1, length).Select(x => String.Format("c{0}.Value", x))); #>
<# string dynamicSelectorTypeParams = String.Join(", ", templParams.Select(x => "IObservedChange")); #>
<# string selectorCall = "selector(" + String.Join(", ", Enumerable.Range(1, length).Select(x => "islot" + x.ToString())) + ")"; #>
<# if (length != 1 && length <= 7) { #>
///
/// WhenAnyValue allows you to observe whenever the value of 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.
///
public static IObservable>> WhenAnyValue>(this TSender This,
<# for(int i=1; i <= length; i++) { #>
Expression>> property<#=i#><# if (i != length) { #>,<# } #>
<# } #>)
{
return This.WhenAny(<#= valuePropertyParams #>,
(<#= valueSelectorParams #>) =>
Tuple.Create(<#= valueSelectorArgs #>));
}
<# } #>
///
/// WhenAnyValue allows you to observe whenever the value of 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.
///
public static IObservable WhenAnyValue>(this TSender This,
<# for(int i=1; i <= length; i++) { #>
Expression>> property<#=i#>,
<# } #>
Func<<#= String.Join(",", templParams) #>, TRet> selector)
{
return This.WhenAny(<#= valuePropertyParams #>,
(<#= valueSelectorParams #>) =>
selector(<#= valueSelectorArgs #>));
}
///
/// 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.
///
public static IObservable WhenAny>(this TSender This,
<# for(int i=1; i <= length; i++) { #>
Expression>> property<#=i#>,
<# } #>
Func<<#= selectorTypeParams #>, TRet> selector)
{
<# if (length == 1){ #>
return This.ObservableForProperty(property<#=1#>, false, false).Select(selector);
<# }else{ #>
return Observable.CombineLatest(
<# for(int i=1; i <= length; i++) { #>
This.ObservableForProperty(property<#=i#>, false, false),
<# } #>
selector
);
<# } #>
}
///
/// 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.
///
public static IObservable WhenAnyDynamic(this TSender This,
<# for(int i=1; i <= length; i++) { #>
Expression property<#=i#>,
<# } #>
Func<<#= dynamicSelectorTypeParams #>, TRet> selector)
{
<# if (length == 1){ #>
return ReactiveNotifyPropertyChangedMixin
.SubscribeToExpressionChain(This, property<#=1#>, false, false).Select(selector);
<# }else{ #>
return Observable.CombineLatest(
<# for(int i=1; i <= length; i++) { #>
ReactiveNotifyPropertyChangedMixin
.SubscribeToExpressionChain(This, property<#=i#>, false, false),
<# } #>
selector
);
<# } #>
}
<# } #>
}
public static class WhenAnyObservableMixin
{
public static IObservable WhenAnyObservable(this TSender This, Expression>> obs1)
{
return This.WhenAny(obs1, x => x.Value.EmptyIfNull()).Switch();
}
<# for(int length=2; length <= maxFuncLength; length++) { #>
<# string paramsStr = String.Join(", ", Enumerable.Range(1, length).Select(x => "Expression>> obs" + x.ToString())); #>
<# string varsStr = String.Join(", ", Enumerable.Range(1, length).Select(x => "obs" + x.ToString())); #>
<# string valsStr = String.Join(", ", Enumerable.Range(1, length).Select(x => "o" + x.ToString() + ".Value.EmptyIfNull()")); #>
public static IObservable WhenAnyObservable(this TSender This, <#= paramsStr #>)
{
return This.WhenAny(<#= varsStr #>, (<#=varsStr.Replace("obs", "o")#>) => new[] {<#= valsStr #>})
.Select(x => x.Merge()).Switch();
}
<# } #>
<# for(int length=2; length <= maxFuncLength; length++) { #>
<# var templParams = Enumerable.Range(1, length).Select(x => "T" + x.ToString()); #>
<# string varsStr = String.Join(", ", Enumerable.Range(1, length).Select(x => "obs" + x.ToString())); #>
<# string valsStr = String.Join(", ", Enumerable.Range(1, length).Select(x => "o" + x.ToString() + ".Value.EmptyIfNull()")); #>
<# string selectorTypeParams = String.Join(", ", templParams); #>
public static IObservable WhenAnyObservable>(this TSender This,
<# for(int i=1; i <= length; i++) { #>
Expression>>> obs<#=i#>,
<# } #>
Func<<#= selectorTypeParams #>, TRet> selector)
{
return This.WhenAny(<#= varsStr #>, (<#=varsStr.Replace("obs", "o")#>) => Observable.CombineLatest(<#= valsStr #>, selector))
.Switch();
}
<# } #>
}
internal static class ObservableExtensions
{
public static IObservable EmptyIfNull(this IObservable @this)
{
return @this ?? Observable.Empty;
}
}
}