add a central cache, for easy data retriveal
This commit is contained in:
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
namespace Hyperbar.Windows.MediaController;
|
namespace Hyperbar.Windows.MediaController;
|
||||||
|
|
||||||
public class MediaControllerFactory(IMediator mediator,
|
public class MediaControllerFactory(IServiceScopeFactory<MediaController> serviceScopeFactory) :
|
||||||
IServiceScopeFactory<MediaController> serviceScopeFactory) :
|
|
||||||
IFactory<GlobalSystemMediaTransportControlsSession, MediaController?>
|
IFactory<GlobalSystemMediaTransportControlsSession, MediaController?>
|
||||||
{
|
{
|
||||||
public MediaController? Create(GlobalSystemMediaTransportControlsSession value)
|
public MediaController? Create(GlobalSystemMediaTransportControlsSession value)
|
||||||
@@ -11,22 +10,6 @@ public class MediaControllerFactory(IMediator mediator,
|
|||||||
if (serviceScopeFactory.Create(value) is MediaController mediaController)
|
if (serviceScopeFactory.Create(value) is MediaController mediaController)
|
||||||
{
|
{
|
||||||
return mediaController;
|
return mediaController;
|
||||||
|
|
||||||
//if (serviceScope.ServiceProvider.GetService<IServiceFactory>() is IServiceFactory serviceFactory)
|
|
||||||
//{
|
|
||||||
// if (serviceFactory.Create<MediaController>(value) is MediaController mediaController)
|
|
||||||
// {
|
|
||||||
// //if (serviceScope.ServiceProvider.GetService<IFactory<MediaControllerViewModel?>>()
|
|
||||||
// // is IFactory<MediaControllerViewModel?> factory)
|
|
||||||
// //{
|
|
||||||
// // if (factory.Create() is MediaControllerViewModel mediaControllerViewModel)
|
|
||||||
// // {
|
|
||||||
// // _ = await mediator.PublishAsync(new Created<MediaControllerViewModel>(mediaControllerViewModel));
|
|
||||||
// // }
|
|
||||||
// //}
|
|
||||||
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public class MediaControllerManager(IMediator mediator,
|
|||||||
IFactory<GlobalSystemMediaTransportControlsSession, MediaController> factory) :
|
IFactory<GlobalSystemMediaTransportControlsSession, MediaController> factory) :
|
||||||
IInitializer
|
IInitializer
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<GlobalSystemMediaTransportControlsSession, MediaController> cachedSessions = [];
|
private readonly List<KeyValuePair<GlobalSystemMediaTransportControlsSession, MediaController>> cachedSessions = [];
|
||||||
|
|
||||||
public async Task InitializeAsync()
|
public async Task InitializeAsync()
|
||||||
{
|
{
|
||||||
@@ -28,7 +28,7 @@ public class MediaControllerManager(IMediator mediator,
|
|||||||
if (factory.Create(session) is MediaController mediaController)
|
if (factory.Create(session) is MediaController mediaController)
|
||||||
{
|
{
|
||||||
await mediator.PublishAsync(new Created<MediaController>(mediaController));
|
await mediator.PublishAsync(new Created<MediaController>(mediaController));
|
||||||
cachedSessions.TryAdd(session, mediaController);
|
cachedSessions.Add(new KeyValuePair<GlobalSystemMediaTransportControlsSession, MediaController>(session, mediaController));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,17 +39,20 @@ public class MediaControllerManager(IMediator mediator,
|
|||||||
sender.GetSessions();
|
sender.GetSessions();
|
||||||
|
|
||||||
foreach (KeyValuePair<GlobalSystemMediaTransportControlsSession, MediaController> session in
|
foreach (KeyValuePair<GlobalSystemMediaTransportControlsSession, MediaController> session in
|
||||||
cachedSessions)
|
cachedSessions.ToList())
|
||||||
{
|
{
|
||||||
if (!sessions.Contains(session.Key))
|
if (!sessions.Any(x => x.SourceAppUserModelId == session.Key.SourceAppUserModelId))
|
||||||
{
|
{
|
||||||
cachedSessions.TryRemove(session);
|
cachedSessions.Remove(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (GlobalSystemMediaTransportControlsSession session in sessions)
|
foreach (GlobalSystemMediaTransportControlsSession session in sessions)
|
||||||
|
{
|
||||||
|
if (!cachedSessions.Any(x => x.Key.SourceAppUserModelId == session.SourceAppUserModelId))
|
||||||
{
|
{
|
||||||
await InitializeSessionAsync(session);
|
await InitializeSessionAsync(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ public class MediaControllerWidgetProvider :
|
|||||||
.AddSingleton<IInitializer, MediaControllerManager>()
|
.AddSingleton<IInitializer, MediaControllerManager>()
|
||||||
.AddTransient<IServiceScopeFactory<MediaController>, ServiceScopeFactory<MediaController>>()
|
.AddTransient<IServiceScopeFactory<MediaController>, ServiceScopeFactory<MediaController>>()
|
||||||
.AddTransient<IServiceScopeProvider<MediaController>, ServiceScopeProvider<MediaController>>()
|
.AddTransient<IServiceScopeProvider<MediaController>, ServiceScopeProvider<MediaController>>()
|
||||||
.AddSingleton<ConcurrentDictionary<MediaController, IServiceScope>>()
|
.AddCache<MediaController, IServiceScope>()
|
||||||
.AddTransient<IFactory<GlobalSystemMediaTransportControlsSession, MediaController?>, MediaControllerFactory>()
|
.AddTransient<IFactory<GlobalSystemMediaTransportControlsSession, MediaController?>, MediaControllerFactory>()
|
||||||
.AddHandler<MediaControllerHandler>()
|
.AddHandler<MediaControllerHandler>()
|
||||||
.AddTransient<IFactory<MediaControllerViewModel?>, MediaControllerViewModelFactory>()
|
.AddTransient<IFactory<MediaControllerViewModel?>, MediaControllerViewModelFactory>()
|
||||||
|
.AddCache<MediaControllerViewModel>()
|
||||||
.AddContentTemplate<MediaControllerViewModel, MediaControllerView>()
|
.AddContentTemplate<MediaControllerViewModel, MediaControllerView>()
|
||||||
.AddContentTemplate<MediaInformationViewModel, MediaInformationView>();
|
.AddContentTemplate<MediaInformationViewModel, MediaInformationView>();
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ public class PrimaryWidgetProvider :
|
|||||||
{
|
{
|
||||||
public void Create(HostBuilderContext comtext, IServiceCollection services) =>
|
public void Create(HostBuilderContext comtext, IServiceCollection services) =>
|
||||||
services.AddConfiguration<PrimaryWidgetConfiguration>()
|
services.AddConfiguration<PrimaryWidgetConfiguration>()
|
||||||
.AddSingleton<ICache<Guid, IWidgetComponentViewModel>, Cache<Guid, IWidgetComponentViewModel>>()
|
.AddCache<Guid, IWidgetComponentViewModel>()
|
||||||
.AddTransient<IFactory<PrimaryCommandConfiguration, IWidgetComponentViewModel?>, WidgetComponentViewModelFactory>()
|
.AddTransient<IFactory<PrimaryCommandConfiguration, IWidgetComponentViewModel?>, WidgetComponentViewModelFactory>()
|
||||||
.AddTransient<IViewModelEnumerator<IWidgetComponentViewModel>, WidgetComponentViewModelEnumerator>()
|
.AddTransient<IViewModelEnumerator<IWidgetComponentViewModel>, WidgetComponentViewModelEnumerator>()
|
||||||
.AddWidgetTemplate<PrimaryWidgetViewModel>()
|
.AddWidgetTemplate<PrimaryWidgetViewModel>()
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public partial class App :
|
|||||||
|
|
||||||
services.AddSingleton<IMediator, Mediator>();
|
services.AddSingleton<IMediator, Mediator>();
|
||||||
services.AddSingleton<IDisposer, Disposer>();
|
services.AddSingleton<IDisposer, Disposer>();
|
||||||
|
services.AddSingleton<IDispatcher, Dispatcher>();
|
||||||
|
|
||||||
services.AddHostedService<AppService>();
|
services.AddHostedService<AppService>();
|
||||||
services.AddConfiguration<AppConfiguration>();
|
services.AddConfiguration<AppConfiguration>();
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using CommunityToolkit.WinUI;
|
||||||
|
using Microsoft.UI.Dispatching;
|
||||||
|
|
||||||
|
namespace Hyperbar.Windows;
|
||||||
|
|
||||||
|
public class Dispatcher :
|
||||||
|
IDispatcher
|
||||||
|
{
|
||||||
|
private DispatcherQueue dispatcherQueue;
|
||||||
|
|
||||||
|
public Dispatcher() => dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||||
|
|
||||||
|
public async Task InvokeAsync(Action action) => await dispatcherQueue.EnqueueAsync(action.Invoke);
|
||||||
|
}
|
||||||
@@ -34,8 +34,10 @@ namespace Hyperbar.Windows
|
|||||||
isolatedServices.AddHostedService<WidgetService>();
|
isolatedServices.AddHostedService<WidgetService>();
|
||||||
|
|
||||||
isolatedServices.AddTransient<ITemplateFactory, TemplateFactory>();
|
isolatedServices.AddTransient<ITemplateFactory, TemplateFactory>();
|
||||||
|
|
||||||
isolatedServices.AddScoped<IMediator, Mediator>();
|
isolatedServices.AddScoped<IMediator, Mediator>();
|
||||||
isolatedServices.AddScoped<IDisposer, Disposer>();
|
isolatedServices.AddScoped<IDisposer, Disposer>();
|
||||||
|
isolatedServices.AddSingleton<IDispatcher, Dispatcher>();
|
||||||
|
|
||||||
isolatedServices.AddScoped<IVirtualKeyboard, VirtualKeyboard>();
|
isolatedServices.AddScoped<IVirtualKeyboard, VirtualKeyboard>();
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,24 @@ namespace Hyperbar;
|
|||||||
|
|
||||||
public static class IServiceCollectionExtensions
|
public static class IServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
|
public static IServiceCollection AddCache<TKey, TValue>(this IServiceCollection services)
|
||||||
|
where TKey :
|
||||||
|
notnull
|
||||||
|
{
|
||||||
|
services.AddSingleton<ICache<TKey, TValue>, Cache<TKey, TValue>>();
|
||||||
|
services.AddTransient(provider => provider.GetService<ICache<TKey, TValue>>()!.Select(x => x.Value));
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddCache<TValue>(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<ICache<TValue>, Cache<TValue>>();
|
||||||
|
services.AddTransient(provider => provider.GetService<ICache<TValue>>()!.Select(x => x));
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services)
|
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services)
|
||||||
where TConfiguration :
|
where TConfiguration :
|
||||||
class, new()
|
class, new()
|
||||||
@@ -16,15 +34,6 @@ public static class IServiceCollectionExtensions
|
|||||||
return services.AddConfiguration<TConfiguration>(typeof(TConfiguration).Name, "Settings.json", null);
|
return services.AddConfiguration<TConfiguration>(typeof(TConfiguration).Name, "Settings.json", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 AddConfiguration<TConfiguration>(this IServiceCollection services,
|
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
|
||||||
TConfiguration? defaults = null)
|
TConfiguration? defaults = null)
|
||||||
where TConfiguration :
|
where TConfiguration :
|
||||||
@@ -134,13 +143,10 @@ public static class IServiceCollectionExtensions
|
|||||||
provider => provider.GetRequiredService<THandler>(), lifetime));
|
provider => provider.GetRequiredService<THandler>(), lifetime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (contract.Name == typeof(IHandler<,>).Name)
|
||||||
|
|
||||||
if (typeof(THandler).GetInterface(typeof(IHandler<,>).Name) is { } requestContract)
|
|
||||||
{
|
{
|
||||||
if (requestContract.GetGenericArguments() is { Length: 2 } arguments)
|
if (contract.GetGenericArguments() is { Length: 2 } arguments)
|
||||||
{
|
{
|
||||||
Type requestType = arguments[0];
|
Type requestType = arguments[0];
|
||||||
Type responseType = arguments[1];
|
Type responseType = arguments[1];
|
||||||
@@ -156,9 +162,21 @@ public static class IServiceCollectionExtensions
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return services;
|
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 AddWidgetTemplate<TWidgetContent>(this IServiceCollection services)
|
public static IServiceCollection AddWidgetTemplate<TWidgetContent>(this IServiceCollection services)
|
||||||
where TWidgetContent :
|
where TWidgetContent :
|
||||||
IWidgetViewModel
|
IWidgetViewModel
|
||||||
|
|||||||
@@ -1,83 +1,68 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Collections.Concurrent;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
|
||||||
namespace Hyperbar;
|
namespace Hyperbar;
|
||||||
|
|
||||||
public class Cache<TKey, TService>(IDisposer disposer) :
|
public class Cache<TValue>(IDisposer disposer) :
|
||||||
ICache<TKey, TService>
|
ICache<TValue>
|
||||||
where TKey : notnull
|
|
||||||
{
|
{
|
||||||
private readonly IDictionary<TKey, TService> cache = new Dictionary<TKey, TService>();
|
private readonly List<TValue> cache = [];
|
||||||
|
|
||||||
public TService this[TKey key]
|
public void Add(TValue value)
|
||||||
{
|
{
|
||||||
get => cache[key];
|
disposer.Add(value!, Disposable.Create(() =>
|
||||||
set => cache[key] = value;
|
{
|
||||||
|
Remove(value);
|
||||||
|
}));
|
||||||
|
|
||||||
|
cache.Add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICollection<TKey> Keys => cache.Keys;
|
public void Clear() => cache.Clear();
|
||||||
|
|
||||||
public ICollection<TService> Values => cache.Values;
|
public IEnumerator<TValue> GetEnumerator() => cache.GetEnumerator();
|
||||||
|
|
||||||
public int Count => cache.Count;
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
public bool IsReadOnly => false;
|
public bool Remove(TValue value) => cache.Remove(value);
|
||||||
|
}
|
||||||
|
|
||||||
public void Add(TKey key, TService value)
|
public class Cache<TKey, TValue>(IDisposer disposer) :
|
||||||
|
ICache<TKey, TValue>
|
||||||
|
where TKey : notnull
|
||||||
|
{
|
||||||
|
private readonly ConcurrentDictionary<TKey, TValue> cache = new();
|
||||||
|
|
||||||
|
public void Add(TKey key,
|
||||||
|
TValue value)
|
||||||
{
|
{
|
||||||
disposer.Add(value!, Disposable.Create(() =>
|
disposer.Add(value!, Disposable.Create(() =>
|
||||||
{
|
{
|
||||||
Remove(key);
|
Remove(key);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
cache.Add(key, value);
|
cache.TryAdd(key, value);
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(KeyValuePair<TKey, TService> item)
|
|
||||||
{
|
|
||||||
cache.Add(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear() => cache.Clear();
|
public void Clear() => cache.Clear();
|
||||||
|
|
||||||
public bool Contains(KeyValuePair<TKey, TService> item)
|
public bool ContainsKey(TKey key) => cache.ContainsKey(key);
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => cache.GetEnumerator();
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
|
public bool Remove(TKey key) => cache.Remove(key, out _);
|
||||||
|
|
||||||
|
public bool TryGetValue(TKey key, out TValue? value)
|
||||||
{
|
{
|
||||||
return cache.Contains(item);
|
if (cache.TryGetValue(key, out value))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsKey(TKey key)
|
value = default;
|
||||||
{
|
return false;
|
||||||
return cache.ContainsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CopyTo(KeyValuePair<TKey, TService>[] array, int arrayIndex)
|
|
||||||
{
|
|
||||||
cache.CopyTo(array, arrayIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<TKey, TService>> GetEnumerator()
|
|
||||||
{
|
|
||||||
return cache.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Remove(TKey key)
|
|
||||||
{
|
|
||||||
return cache.Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Remove(KeyValuePair<TKey, TService> item)
|
|
||||||
{
|
|
||||||
return cache.Remove(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TService value)
|
|
||||||
{
|
|
||||||
return cache.TryGetValue(key, out value);
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return cache.GetEnumerator();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,29 @@
|
|||||||
namespace Hyperbar;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
public interface ICache<TKey, TViewModel> :
|
namespace Hyperbar;
|
||||||
IDictionary<TKey, TViewModel>
|
|
||||||
|
public interface ICache<TValue> :
|
||||||
|
IEnumerable<TValue>
|
||||||
|
{
|
||||||
|
void Add(TValue value);
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
bool Remove(TValue value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICache<TKey, TValue> :
|
||||||
|
IEnumerable<KeyValuePair<TKey, TValue>>
|
||||||
where TKey : notnull
|
where TKey : notnull
|
||||||
{
|
{
|
||||||
|
void Add(TKey key,
|
||||||
|
TValue value);
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
bool ContainsKey(TKey key);
|
||||||
|
|
||||||
|
bool Remove(TKey key);
|
||||||
|
|
||||||
|
bool TryGetValue(TKey key, out TValue? value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
|
|
||||||
namespace Hyperbar;
|
namespace Hyperbar;
|
||||||
|
|
||||||
public class ServiceScopeFactory<TService>(IServiceScopeFactory serviceScopeFactory,
|
public class ServiceScopeFactory<TService>(IServiceScopeFactory serviceScopeFactory,
|
||||||
ConcurrentDictionary<TService, IServiceScope> services) :
|
ICache<TService, IServiceScope> cache) :
|
||||||
IServiceScopeFactory<TService>
|
IServiceScopeFactory<TService>
|
||||||
where TService : notnull
|
where TService : notnull
|
||||||
{
|
{
|
||||||
@@ -16,7 +15,7 @@ public class ServiceScopeFactory<TService>(IServiceScopeFactory serviceScopeFact
|
|||||||
{
|
{
|
||||||
if (serviceFactory.Create<TService>(parameters) is TService service)
|
if (serviceFactory.Create<TService>(parameters) is TService service)
|
||||||
{
|
{
|
||||||
services.TryAdd(service, serviceScope);
|
cache.Add(service, serviceScope);
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
|
|
||||||
namespace Hyperbar;
|
namespace Hyperbar;
|
||||||
|
|
||||||
public class ServiceScopeProvider<TService>(ConcurrentDictionary<TService, IServiceScope> services) :
|
public class ServiceScopeProvider<TService>(ICache<TService, IServiceScope> cache) :
|
||||||
IServiceScopeProvider<TService>
|
IServiceScopeProvider<TService>
|
||||||
where TService : notnull
|
where TService : notnull
|
||||||
{
|
{
|
||||||
public bool TryGet(TService service,
|
public bool TryGet(TService service,
|
||||||
out IServiceScope? serviceScope)
|
out IServiceScope? serviceScope)
|
||||||
{
|
{
|
||||||
if (services.TryGetValue(service, out IServiceScope? value))
|
if (cache.TryGetValue(service, out IServiceScope? value))
|
||||||
{
|
{
|
||||||
serviceScope = value;
|
serviceScope = value;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Reactive.Concurrency;
|
||||||
|
|
||||||
namespace Hyperbar;
|
namespace Hyperbar;
|
||||||
|
|
||||||
public class Mediator(IServiceProvider provider) :
|
public interface IDispatcher
|
||||||
|
{
|
||||||
|
Task InvokeAsync(Action action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Mediator(IServiceProvider provider,
|
||||||
|
IDispatcher dispatcher) :
|
||||||
IMediator
|
IMediator
|
||||||
{
|
{
|
||||||
private readonly SynchronizationContext? context = SynchronizationContext.Current;
|
private readonly SynchronizationContext? context = SynchronizationContext.Current;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<Type, List<dynamic>> subjects = [];
|
private readonly ConcurrentDictionary<Type, List<dynamic>> subjects = [];
|
||||||
|
|
||||||
public ValueTask PublishAsync<TNotification>(TNotification notification,
|
public async ValueTask PublishAsync<TNotification>(TNotification notification,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
where TNotification :
|
where TNotification :
|
||||||
INotification
|
INotification
|
||||||
@@ -31,10 +38,8 @@ public class Mediator(IServiceProvider provider) :
|
|||||||
|
|
||||||
foreach (INotificationHandler<TNotification> handler in handlers)
|
foreach (INotificationHandler<TNotification> handler in handlers)
|
||||||
{
|
{
|
||||||
context?.Post(async state => await handler.Handle(notification, cancellationToken), null);
|
await dispatcher.InvokeAsync(async () => await handler.Handle(notification, cancellationToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValueTask.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<TResponse> SendAsync<TResponse>(IRequest<TResponse> request,
|
public ValueTask<TResponse> SendAsync<TResponse>(IRequest<TResponse> request,
|
||||||
|
|||||||
@@ -283,6 +283,7 @@ public partial class ObservableCollectionViewModel<TItem> :
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IList.Remove(object? value)
|
void IList.Remove(object? value)
|
||||||
{
|
{
|
||||||
if (IsCompatibleObject(value))
|
if (IsCompatibleObject(value))
|
||||||
|
|||||||
Reference in New Issue
Block a user