Medistor reworked to handle ui threading in a cleaner way
This commit is contained in:
@@ -34,21 +34,21 @@ public class MediaController :
|
||||
disposer.Dispose(this);
|
||||
}
|
||||
|
||||
public async ValueTask Handle(Play notification,
|
||||
public async Task Handle(Play notification,
|
||||
CancellationToken cancellationToken) =>
|
||||
await session.TryPlayAsync();
|
||||
|
||||
public async ValueTask Handle(Pause notification,
|
||||
public async Task Handle(Pause notification,
|
||||
CancellationToken cancellationToken) =>
|
||||
await session.TryPauseAsync();
|
||||
|
||||
public async ValueTask Handle(Request<Playback> notification,
|
||||
public async Task Handle(Request<Playback> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await mediator.PublishAsync(new Changed<Playback>(), cancellationToken);
|
||||
}
|
||||
|
||||
public async ValueTask Handle(Request<MediaInformation> _,
|
||||
public async Task Handle(Request<MediaInformation> _,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
using (await asyncLock)
|
||||
|
||||
@@ -4,16 +4,16 @@ namespace Hyperbar.Windows.MediaController;
|
||||
|
||||
public class MediaControllerHandler(IMediator mediator,
|
||||
IServiceScopeProvider<MediaController> scopeProvider,
|
||||
ICache<MediaController, MediaControllerViewModel> cache) :
|
||||
ICache<MediaController, MediaControllerViewModel> cache) :
|
||||
INotificationHandler<Created<MediaController>>
|
||||
{
|
||||
public async ValueTask Handle(Created<MediaController> notification,
|
||||
public async Task Handle(Created<MediaController> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (notification.Value is MediaController mediaController)
|
||||
{
|
||||
if (scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope))
|
||||
{
|
||||
|
||||
if (serviceScope is not null)
|
||||
{
|
||||
if (serviceScope.ServiceProvider.GetService<IFactory<MediaController, MediaControllerViewModel?>>()
|
||||
@@ -27,8 +27,6 @@ public class MediaControllerHandler(IMediator mediator,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public partial class MediaInformationViewModel(IServiceFactory serviceFactory,
|
||||
public ICommand Initialize =>
|
||||
new AsyncRelayCommand(InitializeAsync);
|
||||
|
||||
public ValueTask Handle(Changed<MediaInformation> notification,
|
||||
public Task Handle(Changed<MediaInformation> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (notification.Value is MediaInformation value)
|
||||
@@ -30,7 +30,7 @@ public partial class MediaInformationViewModel(IServiceFactory serviceFactory,
|
||||
Description = value.Description;
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task InitializeAsync() =>
|
||||
|
||||
@@ -6,7 +6,7 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator,
|
||||
ICache<Guid, IWidgetComponentViewModel> cache) :
|
||||
INotificationHandler<ConfigurationChanged<PrimaryWidgetConfiguration>>
|
||||
{
|
||||
public async ValueTask Handle(ConfigurationChanged<PrimaryWidgetConfiguration> notification,
|
||||
public async Task Handle(ConfigurationChanged<PrimaryWidgetConfiguration> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
HashSet<Guid> configurationIds = new(configuration.SelectMany(item => new[] { item }
|
||||
@@ -23,10 +23,10 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator,
|
||||
{
|
||||
if (!cache.ContainsKey(item.Id))
|
||||
{
|
||||
if (factory.Create(item) is IWidgetComponentViewModel value)
|
||||
if (factory.Create(item) is IWidgetComponentViewModel viewModel)
|
||||
{
|
||||
await mediator.PublishAsync(Inserted<IWidgetComponentViewModel>
|
||||
.For<PrimaryWidgetViewModel>(item.Order, value),
|
||||
.For<PrimaryWidgetViewModel>(item.Order, viewModel),
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ public class WidgetComponentViewModelFactory(IServiceFactory service,
|
||||
if (processCommandConfiguration.Commands is { Count: > 0 } childCommandConfigurations)
|
||||
{
|
||||
List<IWidgetComponentViewModel> childViewModels = [];
|
||||
|
||||
foreach (PrimaryCommandConfiguration childCommandConfiguration in childCommandConfigurations)
|
||||
{
|
||||
WidgetComponentViewModel? childViewModel = null;
|
||||
|
||||
@@ -6,9 +6,9 @@ public class AppConfigurationChangedHandler(DesktopBar desktopFlyout,
|
||||
AppConfiguration configuration) :
|
||||
INotificationHandler<ConfigurationChanged<AppConfiguration>>
|
||||
{
|
||||
public ValueTask Handle(ConfigurationChanged<AppConfiguration> notification, CancellationToken cancellationToken)
|
||||
public Task Handle(ConfigurationChanged<AppConfiguration> notification, CancellationToken cancellationToken)
|
||||
{
|
||||
desktopFlyout.Placement = configuration.Placement;
|
||||
return ValueTask.CompletedTask;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -3,12 +3,12 @@
|
||||
namespace Hyperbar.Windows;
|
||||
|
||||
public class KeyAcceleratorHandler(IVirtualKeyboard virtualKeyboard) :
|
||||
IRequestHandler<KeyAccelerator>
|
||||
IHandler<KeyAccelerator>
|
||||
{
|
||||
public ValueTask<Unit> Handle(KeyAccelerator request,
|
||||
public Task<Unit> Handle(KeyAccelerator request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
virtualKeyboard.Send((int)request.Key, request.Modifiers?.Select(modifier => (int)modifier).ToArray() ?? []);
|
||||
return default;
|
||||
return Task.FromResult<Unit>(default);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -3,12 +3,12 @@
|
||||
namespace Hyperbar.Windows;
|
||||
|
||||
public class StartProcessHandler :
|
||||
IRequestHandler<StartProcess>
|
||||
IHandler<StartProcess>
|
||||
{
|
||||
public ValueTask<Unit> Handle(StartProcess request,
|
||||
public Task<Unit> Handle(StartProcess request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Process.Start(request.Process);
|
||||
return default;
|
||||
return Task.FromResult<Unit>(default);
|
||||
}
|
||||
}
|
||||
@@ -138,9 +138,8 @@ public static class IServiceCollectionExtensions
|
||||
{
|
||||
Type notificationType = arguments[0];
|
||||
|
||||
services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime));
|
||||
services.Add(new ServiceDescriptor(typeof(INotificationHandler<>).MakeGenericType(notificationType),
|
||||
provider => provider.GetRequiredService<THandler>(), lifetime));
|
||||
//services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime));
|
||||
services.Add(new ServiceDescriptor(typeof(INotificationHandler<>).MakeGenericType(notificationType), typeof(THandler), lifetime));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +150,7 @@ public static class IServiceCollectionExtensions
|
||||
Type requestType = arguments[0];
|
||||
Type responseType = arguments[1];
|
||||
|
||||
Type wrapperType = typeof(RequestClassHandlerWrapper<,>).MakeGenericType(requestType, responseType);
|
||||
Type wrapperType = typeof(HandlerWrapper<,>).MakeGenericType(requestType, responseType);
|
||||
|
||||
services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime));
|
||||
services.Add(new ServiceDescriptor(wrapperType,
|
||||
@@ -169,14 +168,15 @@ public static class IServiceCollectionExtensions
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddNotificationPipeline<TFromNotification, TToNotification>(this IServiceCollection services)
|
||||
where TFromNotification :
|
||||
INotification
|
||||
where TToNotification :
|
||||
INotification, new()
|
||||
{
|
||||
return services.AddHandler<NotficationPipelineHandler<TFromNotification, TToNotification>>();
|
||||
}
|
||||
//public static IServiceCollection AddNotificationPipeline<TFromNotification, TToNotification>(this IServiceCollection services)
|
||||
// where TFromNotification :
|
||||
// INotification
|
||||
// where TToNotification :
|
||||
// INotification, new()
|
||||
//{
|
||||
// return services.AddHandler<NotficationPipelineHandler<TFromNotification, TToNotification>>();
|
||||
//}
|
||||
|
||||
public static IServiceCollection AddWidgetTemplate<TWidgetContent>(this IServiceCollection services)
|
||||
where TWidgetContent :
|
||||
IWidgetViewModel
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public delegate ValueTask<TResponse> MessageHandlerDelegate<TMessage, TResponse>(TMessage message,
|
||||
public delegate Task<TResponse> HandlerDelegate<TMessage, TResponse>(TMessage message,
|
||||
CancellationToken cancellationToken)
|
||||
where TMessage :
|
||||
notnull,
|
||||
+6
-6
@@ -1,19 +1,19 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public class RequestClassHandlerWrapper<TRequest, TResponse>
|
||||
public class HandlerWrapper<TRequest, TResponse>
|
||||
where TRequest :
|
||||
class,
|
||||
IRequest<TResponse>
|
||||
{
|
||||
private readonly MessageHandlerDelegate<TRequest, TResponse> handler;
|
||||
private readonly HandlerDelegate<TRequest, TResponse> handler;
|
||||
|
||||
public RequestClassHandlerWrapper(IHandler<TRequest, TResponse> concreteHandler,
|
||||
public HandlerWrapper(IHandler<TRequest, TResponse> concreteHandler,
|
||||
IEnumerable<IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours)
|
||||
{
|
||||
MessageHandlerDelegate<TRequest, TResponse> handler = concreteHandler.Handle;
|
||||
HandlerDelegate<TRequest, TResponse> handler = concreteHandler.Handle;
|
||||
foreach (IPipelineBehavior<TRequest, TResponse>? pipeline in pipelineBehaviours.Reverse())
|
||||
{
|
||||
MessageHandlerDelegate<TRequest, TResponse> handlerCopy = handler;
|
||||
HandlerDelegate<TRequest, TResponse> handlerCopy = handler;
|
||||
IPipelineBehavior<TRequest, TResponse> pipelineCopy = pipeline;
|
||||
|
||||
handler = (TRequest message, CancellationToken cancellationToken) =>
|
||||
@@ -23,5 +23,5 @@ public class RequestClassHandlerWrapper<TRequest, TResponse>
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public ValueTask<TResponse> Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken);
|
||||
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken);
|
||||
}
|
||||
@@ -7,13 +7,11 @@ public interface IHandler<in TRequest, TResponse> :
|
||||
where TRequest :
|
||||
IRequest<TResponse>
|
||||
{
|
||||
ValueTask<TResponse> Handle(TRequest request,
|
||||
Task<TResponse> Handle(TRequest request,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface IRequestHandler<in TRequest> :
|
||||
public interface IHandler<in TRequest> :
|
||||
IHandler<TRequest, Unit>
|
||||
where TRequest :
|
||||
IRequest<Unit>
|
||||
{
|
||||
}
|
||||
IRequest<Unit>;
|
||||
@@ -2,21 +2,27 @@
|
||||
|
||||
public interface IMediator
|
||||
{
|
||||
ValueTask PublishAsync<TNotification>(TNotification notification,
|
||||
Task PublishAsync<TNotification>(TNotification notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification;
|
||||
|
||||
ValueTask PublishAsync<TNotification>(CancellationToken cancellationToken = default)
|
||||
Task PublishAsync<TNotification>(TNotification notification,
|
||||
Func<Func<Task>, Task> marshal,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification;
|
||||
|
||||
Task PublishAsync<TNotification>(CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new();
|
||||
|
||||
ValueTask<TResponse> SendAsync<TResponse>(IRequest<TResponse> request,
|
||||
Task<TResponse?> SendAsync<TResponse>(IRequest<TResponse> request,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
ValueTask<object?> SendAsync(object message, CancellationToken
|
||||
Task<object?> SendAsync(object message, CancellationToken
|
||||
cancellationToken = default);
|
||||
|
||||
void Subscribe(object subscriber);
|
||||
|
||||
void Subscribe(object handler);
|
||||
}
|
||||
@@ -5,6 +5,6 @@ public interface INotificationHandler<in TNotification> :
|
||||
where TNotification :
|
||||
INotification
|
||||
{
|
||||
ValueTask Handle(TNotification notification,
|
||||
Task Handle(TNotification notification,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -5,7 +5,7 @@ public interface IPipelineBehavior<TMessage, TResponse>
|
||||
notnull,
|
||||
IMessage
|
||||
{
|
||||
ValueTask<TResponse> Handle(TMessage message,
|
||||
MessageHandlerDelegate<TMessage, TResponse> next,
|
||||
Task<TResponse> Handle(TMessage message,
|
||||
HandlerDelegate<TMessage, TResponse> next,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -7,11 +7,18 @@ public class Mediator(IServiceProvider provider,
|
||||
IDispatcher dispatcher) :
|
||||
IMediator
|
||||
{
|
||||
private readonly SynchronizationContext? context = SynchronizationContext.Current;
|
||||
|
||||
private readonly ConcurrentDictionary<Type, List<dynamic>> subjects = [];
|
||||
|
||||
public async ValueTask PublishAsync<TNotification>(TNotification notification,
|
||||
public Task PublishAsync<TNotification>(TNotification notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification
|
||||
{
|
||||
return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()), cancellationToken);
|
||||
}
|
||||
|
||||
public Task PublishAsync<TNotification>(TNotification notification,
|
||||
Func<Func<Task>, Task> marshal,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification
|
||||
@@ -32,19 +39,21 @@ public class Mediator(IServiceProvider provider,
|
||||
|
||||
foreach (INotificationHandler<TNotification> handler in handlers)
|
||||
{
|
||||
await dispatcher.InvokeAsync(async () => await handler.Handle(notification, cancellationToken));
|
||||
marshal(() => handler.Handle(notification, cancellationToken));
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public ValueTask PublishAsync<TNotification>(CancellationToken cancellationToken = default)
|
||||
public Task PublishAsync<TNotification>(CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new() => PublishAsync(new TNotification(), cancellationToken);
|
||||
new() => PublishAsync(new TNotification(), null, cancellationToken);
|
||||
|
||||
public ValueTask<TResponse> SendAsync<TResponse>(IRequest<TResponse> request,
|
||||
public Task<TResponse?> SendAsync<TResponse>(IRequest<TResponse> request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
dynamic? handler = provider.GetService(typeof(RequestClassHandlerWrapper<,>)
|
||||
dynamic? handler = provider.GetService(typeof(HandlerWrapper<,>)
|
||||
.MakeGenericType(request.GetType(), typeof(TResponse)));
|
||||
|
||||
if (handler is not null)
|
||||
@@ -52,10 +61,10 @@ public class Mediator(IServiceProvider provider,
|
||||
return handler.Handle((dynamic)request, cancellationToken);
|
||||
}
|
||||
|
||||
return default;
|
||||
return Task.FromResult<TResponse?>(default);
|
||||
}
|
||||
|
||||
public ValueTask<object?> SendAsync(object message,
|
||||
public Task<object?> SendAsync(object message,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (message.GetType().GetInterface(typeof(IRequest<>).Name) is { } requestType)
|
||||
@@ -64,7 +73,7 @@ public class Mediator(IServiceProvider provider,
|
||||
{
|
||||
Type responseType = arguments[0];
|
||||
|
||||
dynamic? handler = provider.GetService(typeof(RequestClassHandlerWrapper<,>)
|
||||
dynamic? handler = provider.GetService(typeof(HandlerWrapper<,>)
|
||||
.MakeGenericType(message.GetType(), responseType));
|
||||
|
||||
if (handler is not null)
|
||||
@@ -74,12 +83,12 @@ public class Mediator(IServiceProvider provider,
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
return Task.FromResult<object?>(default);
|
||||
}
|
||||
|
||||
public void Subscribe(object subject)
|
||||
public void Subscribe(object handler)
|
||||
{
|
||||
Type[] interfaceTypes = subject.GetType().GetInterfaces();
|
||||
Type[] interfaceTypes = handler.GetType().GetInterfaces();
|
||||
foreach (Type interfaceType in interfaceTypes.Where(x => x.IsGenericType))
|
||||
{
|
||||
if (interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>))
|
||||
@@ -87,10 +96,10 @@ public class Mediator(IServiceProvider provider,
|
||||
if (interfaceType.GetGenericArguments() is { Length: 1 } arguments)
|
||||
{
|
||||
Type notificationType = arguments[0];
|
||||
subjects.AddOrUpdate(notificationType, [subject], (value, collection) =>
|
||||
subjects.AddOrUpdate(notificationType, [handler], (value, collection) =>
|
||||
{
|
||||
collection.Add(subject);
|
||||
return collection;
|
||||
collection.Add(handler);
|
||||
return collection;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public class NotficationPipelineHandler<TFromNotification, ToNotification>(IMediator mediator) :
|
||||
INotificationHandler<TFromNotification>,
|
||||
IHandler
|
||||
where TFromNotification :
|
||||
INotification
|
||||
where ToNotification :
|
||||
INotification, new()
|
||||
{
|
||||
private readonly IMediator mediator = mediator;
|
||||
|
||||
public ValueTask Handle(TFromNotification notification, CancellationToken cancellationToken) =>
|
||||
mediator.PublishAsync(new ToNotification(), cancellationToken);
|
||||
}
|
||||
@@ -206,7 +206,7 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
IEnumerator IEnumerable.GetEnumerator() =>
|
||||
((IEnumerable)collection).GetEnumerator();
|
||||
|
||||
public ValueTask Handle(Removed<TItem> notification,
|
||||
public Task Handle(Removed<TItem> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (TItem item in this.ToList())
|
||||
@@ -223,10 +223,10 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
}
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public ValueTask Handle(Created<TItem> notification,
|
||||
public Task Handle(Created<TItem> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (notification.Target.Equals(GetType().Name))
|
||||
@@ -237,10 +237,10 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
}
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public ValueTask Handle(Inserted<TItem> notification,
|
||||
public Task Handle(Inserted<TItem> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (notification.Target.Equals(GetType().Name))
|
||||
@@ -251,7 +251,7 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
}
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public int IndexOf(TItem item) =>
|
||||
|
||||
Reference in New Issue
Block a user