Medistor reworked to handle ui threading in a cleaner way
This commit is contained in:
@@ -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