Skip to content

Instantly share code, notes, and snippets.

@kentcb
Created January 20, 2016 08:17
Show Gist options
  • Save kentcb/29caa10e2516565cb6b4 to your computer and use it in GitHub Desktop.
Save kentcb/29caa10e2516565cb6b4 to your computer and use it in GitHub Desktop.
Playing with Interaction APIs
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; }
}
}
@pmbanka
Copy link

pmbanka commented Jan 20, 2016

Just a quick thought - do we need a constraint similar to where TInteraction : NewInteraction<TResult>? Maybe we can work around it using interfaces somehow?

public class InteractionSource<TInteractionResult>
{
    public IObservable<TInteractionResult> Raise(IUserInteraction<TInteractionResult> interaction) { ... }
}

I will try to find time to fiddle with this idea later today.

@mteper
Copy link

mteper commented Jan 20, 2016

Naming thought (can you tell I obsess about naming?): is there a reason not to call RegistrerHandler => Subscribe?

@mteper
Copy link

mteper commented Jan 20, 2016

👍 for @pmbanka's interface idea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment