Last active
January 19, 2018 23:34
-
-
Save MrAntix/1c1ad29e3733c90d312a90e99ba97828 to your computer and use it in GitHub Desktop.
Route events based on type on the same observable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class ObservableExtensions | |
{ | |
public static Builder<TBase> SwitchType<TBase>( | |
this IObservable<TBase> observable) | |
{ | |
return new Builder<TBase>(observable); | |
} | |
public class Builder<TBase> | |
{ | |
readonly IObservable<TBase> _observable; | |
Func<TBase, Task<bool>> _onNext; | |
internal Builder(IObservable<TBase> observable) | |
{ | |
_observable = observable; | |
_onNext = o => Task.FromResult(false); | |
} | |
public Builder<TBase> Case<TCase>( | |
Func<TCase, Task> action) | |
where TCase : class, TBase | |
{ | |
var previousCheck = _onNext; | |
_onNext = async (TBase o) => | |
{ | |
if (await previousCheck(o)) return true; | |
return await IsType(o, action); | |
}; | |
return this; | |
} | |
public Builder<TBase> Case<TCase>(Action<TCase> action) | |
where TCase : class, TBase | |
=> Case(ToAsync(action)); | |
public IDisposable Subscribe( | |
Func<TBase, Task> defaultAction) | |
{ | |
return _observable.Subscribe(async (TBase o) => | |
{ | |
if (await _onNext(o)) return; | |
await defaultAction(o); | |
}); | |
} | |
public IDisposable Subscribe(Action<TBase> defaultAction) | |
=> Subscribe(ToAsync(defaultAction)); | |
public IDisposable Subscribe() | |
{ | |
return _observable.Subscribe(async e => await _onNext(e)); | |
} | |
static async Task<bool> IsType<TCase>(TBase o, Func<TCase, Task> action) | |
where TCase : class, TBase | |
{ | |
if (o is TCase) | |
{ | |
await action(o as TCase); | |
return true; | |
} | |
return false; | |
} | |
static Func<T, Task> ToAsync<T>( | |
Action<T> action) | |
{ | |
return o => | |
{ | |
action(o); | |
return Task.CompletedTask; | |
}; | |
} | |
} | |
} |
The above worked because of the .Else()
, which called the Observable.Subscribe()
method explicitly.
Without this the implicit subscribe didn't work.
Opted for an explicit call to subscribe in the end which suits the pattern better anyway ie .Observable.SomeFunc().Subscribe()
usage
myObservable.SwitchType()
.Case<AnEvent>(e => { })
.Case<AnOtherEvent>(e => { })
.Subscribe()
The .Else()
action can be passed in to the .Subscribe(e => { })
as the default action
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
usage (obsolete see below)