Created
January 20, 2016 08:17
-
-
Save kentcb/29caa10e2516565cb6b4 to your computer and use it in GitHub Desktop.
Playing with Interaction APIs
This file contains hidden or 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 class InteractionSource | |
{ | |
public static readonly InteractionSource Global = new InteractionSource(); | |
private readonly IList<Func<NewInteraction, IObservable<Unit>>> handlers; | |
public InteractionSource() | |
{ | |
this.handlers = new List<Func<NewInteraction, IObservable<Unit>>>(); | |
} | |
public IDisposable RegisterHandler(Func<NewInteraction, Task> handler) | |
{ | |
return RegisterHandler(interaction => handler(interaction).ToObservable()); | |
} | |
public IDisposable RegisterHandler(Action<NewInteraction> handler) | |
{ | |
return RegisterHandler(interaction => { | |
handler(interaction); | |
return Observable.Return(Unit.Default); | |
}); | |
} | |
public IDisposable RegisterHandler(Func<NewInteraction, IObservable<Unit>> handler) | |
{ | |
//var selectiveHandler = (Func<NewInteraction, IObservable<Unit>>)(interaction => { | |
// var castInteraction = interaction as TInteraction; | |
// if (castInteraction == null) { | |
// return Observable.Return(Unit.Default); | |
// } | |
// return handler(castInteraction); | |
//}); | |
//handlers.Add(selectiveHandler); | |
//return Disposable.Create(() => handlers.Remove(selectiveHandler)); | |
handlers.Add(handler); | |
return Disposable.Create(() => handlers.Remove(handler)); | |
} | |
} | |
public class InteractionSource<TInteraction, TResult> : InteractionSource | |
where TInteraction : NewInteraction<TResult> | |
{ | |
public InteractionSource() | |
{ | |
} | |
public IObservable<object> Raise(TInteraction interaction) | |
{ | |
return Observable | |
.StartAsync( | |
(async () => { | |
var handlers = Enumerable.Reverse(this.handlers).ToArray(); | |
foreach (var handler in handlers) { | |
await handler(interaction); | |
if (interaction.IsHandled) { | |
return interaction.resul | |
} | |
} | |
throw new NewUnhandledInteractionException(interaction); | |
})); | |
} | |
} | |
public class NewInteraction | |
{ | |
public bool IsHandled | |
{ | |
get; | |
} | |
} | |
public class NewInteraction<TResult> : NewInteraction | |
{ | |
} | |
public class NewUnhandledInteractionException : Exception | |
{ | |
private readonly NewInteraction interaction; | |
public NewUnhandledInteractionException(NewInteraction interaction) | |
{ | |
this.interaction = interaction; | |
} | |
public NewInteraction Interaction | |
{ | |
get { return this.interaction; } | |
} | |
} |
Naming thought (can you tell I obsess about naming?): is there a reason not to call RegistrerHandler
=> Subscribe
?
👍 for @pmbanka's interface idea
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just a quick thought - do we need a constraint similar to
where TInteraction : NewInteraction<TResult>
? Maybe we can work around it using interfaces somehow?I will try to find time to fiddle with this idea later today.