wip
This commit is contained in:
@@ -24,7 +24,7 @@ public sealed class NavigateAction :
|
||||
{
|
||||
if (frameworkElement.DataContext is IObservableViewModel observableViewModel)
|
||||
{
|
||||
observableViewModel.Mediator.PublishAsync(new Navigate(Path))
|
||||
observableViewModel.Publisher.PublishAsync(new Navigate(Path))
|
||||
.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,15 @@ using Microsoft.UI.Xaml.Markup;
|
||||
|
||||
namespace Hyperbar.UI.Windows;
|
||||
|
||||
public class ViewModelBinder
|
||||
{
|
||||
public void Bind(object viewModel,
|
||||
FrameworkElement view)
|
||||
{
|
||||
view.DataContext ??= viewModel;
|
||||
|
||||
}
|
||||
}
|
||||
public class ViewModelTemplate(IViewModelTemplateDescriptorProvider descriptors) :
|
||||
DataTemplateSelector,
|
||||
IViewModelTemplate
|
||||
@@ -19,7 +28,7 @@ public class ViewModelTemplate(IViewModelTemplateDescriptorProvider descriptors)
|
||||
DependencyObject container) =>
|
||||
SelectTemplateCore(item);
|
||||
|
||||
private DataTemplate CreateDataTemplate(IViewModelTemplateDescriptor descriptor)
|
||||
private static DataTemplate CreateDataTemplate(IViewModelTemplateDescriptor descriptor)
|
||||
{
|
||||
string xamlString = @$"
|
||||
<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
using Hyperbar.Interop.Windows;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.Graphics;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace Hyperbar.UI.Windows;
|
||||
|
||||
public class NavigationItemTemplateSelector :
|
||||
DataTemplateSelector
|
||||
{
|
||||
|
||||
}
|
||||
public static class WindowExtensions
|
||||
{
|
||||
public static WindowMessageListener CreateMessageListener(this Window window) =>
|
||||
|
||||
@@ -20,7 +20,7 @@ public class WindowHandler :
|
||||
public Task Handle(Navigate<Window> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Template is Window window)
|
||||
if (args.View is Window window)
|
||||
{
|
||||
if (window.Content is FrameworkElement content)
|
||||
{
|
||||
@@ -33,8 +33,8 @@ public class WindowHandler :
|
||||
}
|
||||
}
|
||||
|
||||
//ViewModelBinder.Bind(args.ViewModel, content);
|
||||
window.Closed += HandleClosed;
|
||||
content.DataContext = args.Content;
|
||||
}
|
||||
|
||||
window.Activate();
|
||||
|
||||
@@ -5,10 +5,11 @@ namespace Hyperbar.Widget.MediaController.Windows;
|
||||
|
||||
public partial class MediaButtonViewModel<TMediaButton>(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
IRelayCommand invokeCommand) :
|
||||
WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer),
|
||||
WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer),
|
||||
INotificationHandler<Changed<MediaButton<TMediaButton>>>,
|
||||
IMediaButtonViewModel
|
||||
{
|
||||
@@ -29,5 +30,5 @@ public partial class MediaButtonViewModel<TMediaButton>(IServiceProvider service
|
||||
}
|
||||
|
||||
public override async Task InitializeAsync() =>
|
||||
await Mediator.PublishAsync<Request<TMediaButton>>();
|
||||
await Publisher.PublishAsync<Request<TMediaButton>>();
|
||||
}
|
||||
@@ -14,23 +14,24 @@ public class MediaController :
|
||||
IDisposable
|
||||
{
|
||||
private readonly IDisposer disposer;
|
||||
private readonly IMediator mediator;
|
||||
private readonly IPublisher publisher;
|
||||
private readonly GlobalSystemMediaTransportControlsSession session;
|
||||
|
||||
private bool isNextEnabled;
|
||||
private bool isPreviousEnabled;
|
||||
private GlobalSystemMediaTransportControlsSessionPlaybackStatus playbackStatus;
|
||||
|
||||
public MediaController(IMediator mediator,
|
||||
public MediaController(IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
GlobalSystemMediaTransportControlsSession session)
|
||||
{
|
||||
this.mediator = mediator;
|
||||
this.publisher = publisher;
|
||||
this.disposer = disposer;
|
||||
this.session = session;
|
||||
|
||||
disposer.Add(this);
|
||||
mediator.Subscribe(this);
|
||||
subscriber.Add(this);
|
||||
|
||||
session.MediaPropertiesChanged += OnMediaPropertiesChanged;
|
||||
session.PlaybackInfoChanged += OnPlaybackInfoChanged;
|
||||
@@ -117,7 +118,7 @@ public class MediaController :
|
||||
buffer = memoryStream.ToArray();
|
||||
}
|
||||
|
||||
await mediator.PublishAsync(new Changed<MediaInformation>(new MediaInformation(mediaProperties.Title,
|
||||
await publisher.PublishAsync(new Changed<MediaInformation>(new MediaInformation(mediaProperties.Title,
|
||||
mediaProperties.Artist, buffer)));
|
||||
}
|
||||
catch
|
||||
@@ -133,7 +134,7 @@ public class MediaController :
|
||||
GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo =
|
||||
session.GetPlaybackInfo();
|
||||
|
||||
await mediator.PublishAsync(new Changed<MediaButton<MediaPlayPauseButton>>(new
|
||||
await publisher.PublishAsync(new Changed<MediaButton<MediaPlayPauseButton>>(new
|
||||
MediaButton<MediaPlayPauseButton>(playbackInfo.PlaybackStatus is
|
||||
GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing ?
|
||||
new MediaButtonPlaying() :
|
||||
@@ -142,7 +143,7 @@ public class MediaController :
|
||||
bool isPreviousEnabled = playbackInfo.Controls.IsPreviousEnabled;
|
||||
if (this.isPreviousEnabled != isPreviousEnabled)
|
||||
{
|
||||
await mediator.PublishAsync(new Changed<MediaButton<MediaPreviousButton>>(new
|
||||
await publisher.PublishAsync(new Changed<MediaButton<MediaPreviousButton>>(new
|
||||
MediaButton<MediaPreviousButton>(isPreviousEnabled ? new MediaButtonEnabled() :
|
||||
new MediaButtonDisabled())));
|
||||
|
||||
@@ -152,7 +153,7 @@ public class MediaController :
|
||||
bool isNextEnabled = playbackInfo.Controls.IsNextEnabled;
|
||||
if (this.isNextEnabled != isNextEnabled)
|
||||
{
|
||||
await mediator.PublishAsync(new Changed<MediaButton<MediaNextButton>>(new
|
||||
await publisher.PublishAsync(new Changed<MediaButton<MediaNextButton>>(new
|
||||
MediaButton<MediaNextButton>(isNextEnabled ? new MediaButtonEnabled() :
|
||||
new MediaButtonDisabled())));
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Hyperbar.Widget.MediaController.Windows;
|
||||
|
||||
public class MediaControllerHandler(IMediator mediator,
|
||||
public class MediaControllerHandler(IPublisher publisher,
|
||||
IServiceScopeProvider<MediaController> scopeProvider,
|
||||
ICache<MediaController, MediaControllerViewModel> cache) :
|
||||
INotificationHandler<Create<MediaController>>,
|
||||
@@ -18,7 +18,7 @@ public class MediaControllerHandler(IMediator mediator,
|
||||
factory.Create(mediaController) is MediaControllerViewModel viewModel)
|
||||
{
|
||||
cache.Add(mediaController, viewModel);
|
||||
await mediator.PublishAsync(new Create<MediaControllerViewModel>(viewModel), cancellationToken);
|
||||
await publisher.PublishAsync(new Create<MediaControllerViewModel>(viewModel), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class MediaControllerHandler(IMediator mediator,
|
||||
cache.TryGetValue(mediaController, out MediaControllerViewModel? viewModel) &&
|
||||
viewModel is not null)
|
||||
{
|
||||
await mediator.PublishAsync(new Remove<MediaControllerViewModel>(viewModel), cancellationToken);
|
||||
await publisher.PublishAsync(new Remove<MediaControllerViewModel>(viewModel), cancellationToken);
|
||||
cache.Remove(mediaController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using Windows.Media.Control;
|
||||
|
||||
namespace Hyperbar.Widget.MediaController.Windows;
|
||||
|
||||
public class MediaControllerService(IMediator mediator,
|
||||
public class MediaControllerService(IPublisher publisher,
|
||||
IFactory<GlobalSystemMediaTransportControlsSession, MediaController> factory) :
|
||||
IHostedService
|
||||
{
|
||||
@@ -34,7 +34,7 @@ public class MediaControllerService(IMediator mediator,
|
||||
{
|
||||
if (factory.Create(session) is MediaController mediaController)
|
||||
{
|
||||
await mediator.PublishAsync(new Create<MediaController>(mediaController));
|
||||
await publisher.PublishAsync(new Create<MediaController>(mediaController));
|
||||
cache.Add(new KeyValuePair<GlobalSystemMediaTransportControlsSession, MediaController>(session,
|
||||
mediaController));
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class MediaControllerService(IMediator mediator,
|
||||
{
|
||||
if (!sessions.Any(x => x.SourceAppUserModelId == session.Key.SourceAppUserModelId))
|
||||
{
|
||||
await mediator.PublishAsync(new Remove<MediaController>(session.Value));
|
||||
await publisher.PublishAsync(new Remove<MediaController>(session.Value));
|
||||
cache.Remove(session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,21 +10,22 @@ public class MediaControllerViewModel :
|
||||
public MediaControllerViewModel(IViewModelTemplate template,
|
||||
IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer)
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
|
||||
Add<MediaInformationViewModel>();
|
||||
|
||||
Add<MediaButtonViewModel<MediaPreviousButton>>(new RelayCommand(async () =>
|
||||
await mediator.PublishAsync<Request<MediaPrevious>>()));
|
||||
await publisher.PublishAsync<Request<MediaPrevious>>()));
|
||||
|
||||
Add<MediaButtonViewModel<MediaPlayPauseButton>>(new RelayCommand(async () =>
|
||||
await mediator.PublishAsync<Request<MediaPlayPause>>()));
|
||||
await publisher.PublishAsync<Request<MediaPlayPause>>()));
|
||||
|
||||
Add<MediaButtonViewModel<MediaNextButton>>(new RelayCommand(async () =>
|
||||
await mediator.PublishAsync<Request<MediaNext>>()));
|
||||
await publisher.PublishAsync<Request<MediaNext>>()));
|
||||
}
|
||||
|
||||
public IViewModelTemplate Template { get; }
|
||||
|
||||
@@ -5,10 +5,11 @@ namespace Hyperbar.Widget.MediaController.Windows;
|
||||
public class MediaControllerWidgetViewModel(IViewModelTemplate template,
|
||||
IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<MediaControllerViewModel> items) :
|
||||
ObservableCollectionViewModel<MediaControllerViewModel>(serviceProvider, serviceFactory, mediator, disposer, items),
|
||||
ObservableCollectionViewModel<MediaControllerViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer, items),
|
||||
IWidgetViewModel
|
||||
{
|
||||
public IViewModelTemplate Template => template;
|
||||
|
||||
@@ -4,9 +4,10 @@ namespace Hyperbar.Widget.MediaController.Windows;
|
||||
|
||||
public partial class MediaInformationViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) :
|
||||
WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer),
|
||||
WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer),
|
||||
INotificationHandler<Changed<MediaInformation>>
|
||||
{
|
||||
[ObservableProperty]
|
||||
@@ -32,5 +33,5 @@ public partial class MediaInformationViewModel(IServiceProvider serviceProvider,
|
||||
}
|
||||
|
||||
public override async Task InitializeAsync() =>
|
||||
await Mediator.PublishAsync<Request<MediaInformation>>();
|
||||
await Publisher.PublishAsync<Request<MediaInformation>>();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using Hyperbar.Widget;
|
||||
namespace Hyperbar.Widget.Primary.Windows;
|
||||
|
||||
namespace Hyperbar.Widget.Primary.Windows;
|
||||
|
||||
public class PrimaryWidgetConfigurationHandler(IMediator mediator,
|
||||
public class PrimaryWidgetConfigurationHandler(IPublisher publisher,
|
||||
PrimaryWidgetConfiguration configuration,
|
||||
IFactory<PrimaryCommandConfiguration, IWidgetComponentViewModel?> factory,
|
||||
IProvider<PrimaryCommandConfiguration, IWidgetComponentViewModel?> provider,
|
||||
@@ -44,7 +42,7 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator,
|
||||
if (moved.Value is PrimaryCommandConfiguration configuration &&
|
||||
provider.Get(configuration) is IWidgetComponentViewModel viewModel)
|
||||
{
|
||||
await mediator.PublishAsync(new Move<IWidgetComponentViewModel>(configuration.Order, viewModel),
|
||||
await publisher.PublishAsync(new Move<IWidgetComponentViewModel>(configuration.Order, viewModel),
|
||||
moved.Key.ParentId == Guid.Empty ? nameof(PrimaryWidgetViewModel) : moved.Key.ParentId,
|
||||
cancellationToken);
|
||||
|
||||
@@ -61,8 +59,7 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator,
|
||||
if (added.Value is PrimaryCommandConfiguration configuration &&
|
||||
factory.Create(configuration) is IWidgetComponentViewModel viewModel)
|
||||
{
|
||||
await mediator.PublishAsync(
|
||||
new Insert<IWidgetComponentViewModel>(configuration.Order, viewModel),
|
||||
await publisher.PublishAsync(new Insert<IWidgetComponentViewModel>(configuration.Order, viewModel),
|
||||
added.Key.ParentId == Guid.Empty ? nameof(PrimaryWidgetViewModel) : added.Key.ParentId,
|
||||
cancellationToken);
|
||||
|
||||
@@ -78,8 +75,7 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator,
|
||||
if (removed.Value is PrimaryCommandConfiguration configuration &&
|
||||
provider.Get(configuration) is IWidgetComponentViewModel viewModel)
|
||||
{
|
||||
await mediator.PublishAsync(
|
||||
new Remove<IWidgetComponentViewModel>(viewModel),
|
||||
await publisher.PublishAsync(new Remove<IWidgetComponentViewModel>(viewModel),
|
||||
removed.Key.ParentId == Guid.Empty ? nameof(PrimaryWidgetViewModel) : removed.Key.ParentId,
|
||||
cancellationToken);
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ namespace Hyperbar.Widget.Primary.Windows;
|
||||
[NotificationHandler(nameof(PrimaryWidgetViewModel))]
|
||||
public class PrimaryWidgetViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableCollectionViewModel<IWidgetComponentViewModel>(serviceProvider, serviceFactory, mediator, disposer),
|
||||
ObservableCollectionViewModel<IWidgetComponentViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer),
|
||||
IWidgetViewModel;
|
||||
@@ -1,14 +1,13 @@
|
||||
using Hyperbar.Widget;
|
||||
|
||||
namespace Hyperbar.Widget.Primary.Windows;
|
||||
namespace Hyperbar.Widget.Primary.Windows;
|
||||
|
||||
public class WidgetComponentViewModelEnumerator(PrimaryWidgetConfiguration configuration,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
IFactory<PrimaryCommandConfiguration, IWidgetComponentViewModel?> factory,
|
||||
ICache<(Guid ParentId, Guid Id), PrimaryCommandConfiguration> cache) :
|
||||
INotificationHandler<Enumerate<IWidgetComponentViewModel>>
|
||||
{
|
||||
public async Task Handle(Enumerate<IWidgetComponentViewModel> notification, CancellationToken cancellationToken)
|
||||
public async Task Handle(Enumerate<IWidgetComponentViewModel> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Stack<(Guid, List<PrimaryCommandConfiguration>)> stack = new();
|
||||
stack.Push((Guid.Empty, configuration.Commands));
|
||||
@@ -30,7 +29,7 @@ public class WidgetComponentViewModelEnumerator(PrimaryWidgetConfiguration confi
|
||||
{
|
||||
if (factory.Create(item) is IWidgetComponentViewModel viewModel)
|
||||
{
|
||||
await mediator.PublishAsync(new Create<IWidgetComponentViewModel>(viewModel), nameof(PrimaryWidgetViewModel),
|
||||
await publisher.PublishAsync(new Create<IWidgetComponentViewModel>(viewModel), nameof(PrimaryWidgetViewModel),
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,13 @@ namespace Hyperbar.Widget;
|
||||
[NotificationHandler(nameof(Id))]
|
||||
public partial class WidgetButtonViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
Guid id,
|
||||
string? text = null,
|
||||
string? icon = null,
|
||||
RelayCommand? invokeCommand = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer)
|
||||
RelayCommand? invokeCommand = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string? icon = icon;
|
||||
|
||||
@@ -6,17 +6,19 @@ public partial class WidgetComponentViewModel :
|
||||
{
|
||||
public WidgetComponentViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<IWidgetComponentViewModel> items) : base(serviceProvider, serviceFactory, mediator, disposer, items)
|
||||
IEnumerable<IWidgetComponentViewModel> items) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer, items)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public WidgetComponentViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer)
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Hyperbar.Widget;
|
||||
|
||||
public class WidgetExtensionEnumerator(IFactory<Type, IWidget> factory,
|
||||
IHostEnvironment hostEnvironment,
|
||||
IMediator mediator) :
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<Enumerate<WidgetExtension>>
|
||||
{
|
||||
public Task Handle(Enumerate<WidgetExtension> args,
|
||||
@@ -29,7 +29,7 @@ public class WidgetExtensionEnumerator(IFactory<Type, IWidget> factory,
|
||||
{
|
||||
if (factory.Create(widgetType) is IWidget widget)
|
||||
{
|
||||
await mediator.PublishAsync(new Create<WidgetExtension>(new WidgetExtension(widget,
|
||||
await publisher.PublishAsync(new Create<WidgetExtension>(new WidgetExtension(widget,
|
||||
new WidgetAssembly(assembly))), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Hyperbar.Widget;
|
||||
|
||||
public class WidgetExtensionHandler(IServiceProvider provider,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
IProxyServiceCollection<IWidgetBuilder> typedServices) :
|
||||
INotificationHandler<Create<WidgetExtension>>
|
||||
{
|
||||
@@ -22,7 +22,7 @@ public class WidgetExtensionHandler(IServiceProvider provider,
|
||||
});
|
||||
|
||||
IWidgetHost host = builder.Build();
|
||||
await mediator.PublishAsync(new Create<IWidgetHost>(host),
|
||||
await publisher.PublishAsync(new Create<IWidgetHost>(host),
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace Hyperbar.Widget;
|
||||
|
||||
public class WidgetExtensionInitializer(IMediator mediator) :
|
||||
public class WidgetExtensionInitializer(IPublisher publisher) :
|
||||
IInitializer
|
||||
{
|
||||
public async Task InitializeAsync() =>
|
||||
await mediator.PublishAsync<Enumerate<WidgetExtension>>();
|
||||
await publisher.PublishAsync<Enumerate<WidgetExtension>>();
|
||||
}
|
||||
@@ -7,17 +7,17 @@ public sealed class WidgetHost :
|
||||
IWidgetHost
|
||||
{
|
||||
private readonly IServiceProvider services;
|
||||
private readonly IMediator mediator;
|
||||
private readonly IPublisher publisher;
|
||||
private readonly IProxyService<IMediator> proxyMediator;
|
||||
private readonly IEnumerable<IHostedService> hostedServices;
|
||||
|
||||
public WidgetHost(IServiceProvider services,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
IProxyService<IMediator> proxyMediator,
|
||||
IEnumerable<IHostedService> hostedServices)
|
||||
{
|
||||
this.services = services;
|
||||
this.mediator = mediator;
|
||||
this.publisher = publisher;
|
||||
this.proxyMediator = proxyMediator;
|
||||
this.hostedServices = hostedServices;
|
||||
}
|
||||
@@ -41,11 +41,11 @@ public sealed class WidgetHost :
|
||||
|
||||
if (proxyMediator.Proxy is IMediator mediator)
|
||||
{
|
||||
await mediator.PublishAsync(new Started<IWidgetHost>(this),
|
||||
await publisher.PublishAsync(new Started<IWidgetHost>(this),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
await this.mediator.PublishAsync(new Started<IWidgetHost>(this),
|
||||
await this.publisher.PublishAsync(new Started<IWidgetHost>(this),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,13 @@ namespace Hyperbar.Widget;
|
||||
[NotificationHandler(nameof(Id))]
|
||||
public partial class WidgetMenuViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
Guid id = default,
|
||||
string? text = null,
|
||||
string? icon = null,
|
||||
RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer)
|
||||
RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private IRelayCommand? click = command;
|
||||
|
||||
@@ -6,13 +6,14 @@ namespace Hyperbar.Widget;
|
||||
[NotificationHandler(nameof(Id))]
|
||||
public partial class WidgetSplitButtonViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<IWidgetComponentViewModel> items,
|
||||
Guid id = default,
|
||||
string? text = null,
|
||||
string? icon = null,
|
||||
RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer, items)
|
||||
RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, items)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private IRelayCommand? click = command;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Hyperbar.Widget;
|
||||
|
||||
public class WidgetStartedHandler(IMediator mediator) :
|
||||
public class WidgetStartedHandler(IPublisher publisher) :
|
||||
INotificationHandler<Started<IWidgetHost>>
|
||||
{
|
||||
public async Task Handle(Started<IWidgetHost> notification,
|
||||
@@ -12,7 +12,7 @@ public class WidgetStartedHandler(IMediator mediator) :
|
||||
{
|
||||
if (host.Services.GetService<IWidgetViewModel>() is IWidgetViewModel viewModel)
|
||||
{
|
||||
await mediator.PublishAsync(new Create<IWidgetViewModel>(viewModel),
|
||||
await publisher.PublishAsync(new Create<IWidgetViewModel>(viewModel),
|
||||
nameof(IWidgetHostViewModel), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Hyperbar.Widget;
|
||||
|
||||
public class WidgetViewModelEnumerator(IWidgetHost host,
|
||||
IMediator mediator) :
|
||||
IPublisher publisher) :
|
||||
INotificationHandler<Enumerate<IWidgetViewModel>>
|
||||
{
|
||||
public async Task Handle(Enumerate<IWidgetViewModel> notification,
|
||||
@@ -13,7 +13,7 @@ public class WidgetViewModelEnumerator(IWidgetHost host,
|
||||
{
|
||||
foreach (IWidgetViewModel viewModel in viewModels)
|
||||
{
|
||||
await mediator.PublishAsync(new Create<IWidgetViewModel>(viewModel),
|
||||
await publisher.PublishAsync(new Create<IWidgetViewModel>(viewModel),
|
||||
nameof(IWidgetHostViewModel), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,12 @@
|
||||
<Application
|
||||
x:Class="Hyperbar.Windows.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="using:Hyperbar.UI.Windows">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<DataTemplate x:Key="DefaultDataTemplate">
|
||||
<ui:ViewModelTemplatePresenter />
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -10,8 +10,9 @@ public partial class ApplicationBarViewModel :
|
||||
public ApplicationBarViewModel(IViewModelTemplate template,
|
||||
IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer)
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
public class GeneralSettingsNavigationViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
string text) :
|
||||
NavigationViewModel(serviceProvider, serviceFactory, mediator, disposer, text)
|
||||
NavigationViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, text)
|
||||
{
|
||||
}
|
||||
@@ -7,10 +7,11 @@ namespace Hyperbar.Widget;
|
||||
public partial class PrimaryViewModel(IViewModelTemplate template,
|
||||
IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
int index) :
|
||||
ObservableCollectionViewModel<IWidgetViewModel>(serviceProvider, serviceFactory, mediator, disposer),
|
||||
ObservableCollectionViewModel<IWidgetViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer),
|
||||
IWidgetHostViewModel
|
||||
{
|
||||
[ObservableProperty]
|
||||
|
||||
@@ -13,9 +13,10 @@ public partial class SecondaryViewModel :
|
||||
public SecondaryViewModel(IViewModelTemplate template,
|
||||
IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
int index) : base(serviceProvider, serviceFactory, mediator, disposer)
|
||||
int index) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
this.index = index;
|
||||
|
||||
@@ -5,9 +5,9 @@ namespace Hyperbar.Windows;
|
||||
public partial class SettingsButtonViewModel(IViewModelTemplate template,
|
||||
IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
IDisposer disposer) :
|
||||
ObservableViewModel(serviceProvider, serviceFactory, mediator, disposer)
|
||||
ObservableViewModel(serviceProvider, serviceFactory, publisher, disposer)
|
||||
{
|
||||
public IViewModelTemplate Template => template;
|
||||
}
|
||||
@@ -7,9 +7,10 @@ public partial class SettingsViewModel :
|
||||
{
|
||||
public SettingsViewModel(IViewModelTemplate template,
|
||||
IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer)
|
||||
IServiceFactory serviceFactory,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
|
||||
{
|
||||
Template = template;
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
public class WidgetNavigationViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
string text) :
|
||||
NavigationViewModel(serviceProvider, serviceFactory, mediator, disposer, text)
|
||||
NavigationViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, text)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
public class WidgetSettingsNavigationViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
string text) :
|
||||
NavigationViewModel<WidgetNavigationViewModel>(serviceProvider, serviceFactory, mediator, disposer, text)
|
||||
NavigationViewModel<WidgetNavigationViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer, text)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public class ConfigurationInitializer<TConfiguration>(IMediator mediator,
|
||||
public class ConfigurationInitializer<TConfiguration>(IPublisher publisher,
|
||||
IConfigurationMonitor<TConfiguration> monitor,
|
||||
IConfigurationReader<TConfiguration> reader,
|
||||
IConfigurationWriter<TConfiguration> writer,
|
||||
@@ -21,7 +21,7 @@ public class ConfigurationInitializer<TConfiguration>(IMediator mediator,
|
||||
}
|
||||
}
|
||||
|
||||
await mediator.PublishAsync(new Changed<TConfiguration>(configuration));
|
||||
await publisher.PublishAsync(new Changed<TConfiguration>(configuration));
|
||||
await monitor.InitializeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
public class ConfigurationMonitor<TConfiguration>(IConfigurationFile<TConfiguration> configurationFile,
|
||||
IConfigurationReader<TConfiguration> reader,
|
||||
IMediator mediator) :
|
||||
IPublisher publisher) :
|
||||
IConfigurationMonitor<TConfiguration>
|
||||
where TConfiguration :
|
||||
class
|
||||
@@ -16,7 +16,7 @@ public class ConfigurationMonitor<TConfiguration>(IConfigurationFile<TConfigurat
|
||||
{
|
||||
if (reader.Read() is { } configuration)
|
||||
{
|
||||
await mediator.PublishAsync(new Changed<TConfiguration>(configuration));
|
||||
await publisher.PublishAsync(new Changed<TConfiguration>(configuration));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public class ConfigurationValueChangedNotification<TConfiguration, TValue>(IMediator mediator,
|
||||
public class ConfigurationValueChangedNotification<TConfiguration, TValue>(IPublisher publisher,
|
||||
Func<TConfiguration, Action<TValue>> factory) :
|
||||
IConfigurationValueChangedNotification<TConfiguration>
|
||||
where TConfiguration :
|
||||
@@ -18,7 +18,7 @@ public class ConfigurationValueChangedNotification<TConfiguration, TValue>(IMedi
|
||||
if (value is null || !value.Equals(newValue))
|
||||
{
|
||||
value = newValue;
|
||||
await mediator.PublishAsync(new Changed<TValue>(value));
|
||||
await publisher.PublishAsync(new Changed<TValue>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public static class IServiceCollectionExtensions
|
||||
class, new()
|
||||
{
|
||||
services.AddSingleton<IConfigurationValueChangedNotification<TConfiguration>>(provider =>
|
||||
new ConfigurationValueChangedNotification<TConfiguration, TValue>(provider.GetRequiredService<IMediator>(),
|
||||
new ConfigurationValueChangedNotification<TConfiguration, TValue>(provider.GetRequiredService<IPublisher>(),
|
||||
factory));
|
||||
|
||||
return services;
|
||||
@@ -237,18 +237,6 @@ public static class IServiceCollectionExtensions
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
public static IServiceCollection AddNotificationRelay<TFromNotification,
|
||||
TToNotification>(this IServiceCollection services)
|
||||
where TFromNotification :
|
||||
INotification
|
||||
where TToNotification :
|
||||
INotification, new()
|
||||
{
|
||||
return services.AddHandler<NotficationRelayHandler<TFromNotification,
|
||||
TToNotification>>();
|
||||
}
|
||||
|
||||
public static IServiceCollection AddRange(this IServiceCollection services,
|
||||
IServiceCollection fromServices)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class AsyncLock(int initial = 1,
|
||||
int maximum = 1) :
|
||||
IDisposable
|
||||
{
|
||||
private readonly SemaphoreSlim semaphore = new(initial, maximum);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
semaphore.Release();
|
||||
}
|
||||
|
||||
public TaskAwaiter<AsyncLock> GetAwaiter() => LockAsync().GetAwaiter();
|
||||
|
||||
private async Task<AsyncLock> LockAsync()
|
||||
{
|
||||
await semaphore.WaitAsync();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -11,24 +11,25 @@ public class Cache<TValue>(IDisposer disposer) :
|
||||
|
||||
public void Add(TValue value)
|
||||
{
|
||||
disposer.Add(value!, Disposable.Create(() =>
|
||||
if (value is null)
|
||||
{
|
||||
Remove(value);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
disposer.Add(value, Disposable.Create(() => Remove(value)));
|
||||
cache.Add(value);
|
||||
}
|
||||
|
||||
public void Clear() => cache.Clear();
|
||||
|
||||
public System.Collections.Generic.IEnumerator<TValue> GetEnumerator() => cache.GetEnumerator();
|
||||
public IEnumerator<TValue> GetEnumerator() => cache.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public bool Remove(TValue value) => cache.Remove(value);
|
||||
}
|
||||
|
||||
public class Cache<TKey, TValue>(IDisposer disposer) :
|
||||
public class Cache<TKey, TValue> :
|
||||
ICache<TKey, TValue>
|
||||
where TKey :
|
||||
notnull
|
||||
@@ -47,7 +48,7 @@ public class Cache<TKey, TValue>(IDisposer disposer) :
|
||||
|
||||
public bool ContainsKey(TKey key) => cache.ContainsKey(key);
|
||||
|
||||
public System.Collections.Generic.IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => cache.GetEnumerator();
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => cache.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
|
||||
@@ -1,30 +1,9 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class AsyncLock(int initial = 1,
|
||||
int maximum = 1) : IDisposable
|
||||
{
|
||||
private readonly SemaphoreSlim semaphore = new(initial, maximum);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
semaphore.Release();
|
||||
}
|
||||
|
||||
public TaskAwaiter<AsyncLock> GetAwaiter() => LockAsync().GetAwaiter();
|
||||
|
||||
private async Task<AsyncLock> LockAsync()
|
||||
{
|
||||
await semaphore.WaitAsync();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Disposer :
|
||||
IDisposer
|
||||
{
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IEnumerator<TItem>
|
||||
{
|
||||
IEnumerable<TItem?> Get();
|
||||
}
|
||||
@@ -6,7 +6,7 @@ public interface IObservableViewModel :
|
||||
{
|
||||
public IDisposer Disposer { get; }
|
||||
|
||||
public IMediator Mediator { get; }
|
||||
public IPublisher Publisher { get; }
|
||||
|
||||
public IServiceFactory ServiceFactory { get; }
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@ namespace Hyperbar;
|
||||
public record Navigate(object Key) :
|
||||
INotification;
|
||||
|
||||
public record Navigate<TTemplate>(TTemplate Template, object Content) :
|
||||
public record Navigate<TView>(TView View, object ViewModel) :
|
||||
INotification;
|
||||
|
||||
@@ -7,16 +7,16 @@ public class NavigateHandler :
|
||||
{
|
||||
private readonly IViewModelTemplateDescriptorProvider contentTemplateDescriptors;
|
||||
private readonly IServiceProvider provider;
|
||||
private readonly IMediator mediator;
|
||||
private readonly IPublisher publisher;
|
||||
private readonly IEnumerable<INavigationDescriptor> navigationDescriptors;
|
||||
|
||||
public NavigateHandler(IServiceProvider provider,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
IEnumerable<INavigationDescriptor> navigationDescriptors,
|
||||
IViewModelTemplateDescriptorProvider contentTemplateDescriptors)
|
||||
{
|
||||
this.provider = provider;
|
||||
this.mediator = mediator;
|
||||
this.publisher = publisher;
|
||||
this.navigationDescriptors = navigationDescriptors;
|
||||
this.contentTemplateDescriptors = contentTemplateDescriptors;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class NavigateHandler :
|
||||
if (Activator.CreateInstance(navigateType,
|
||||
new object[] { template, content }) is object navigate)
|
||||
{
|
||||
await mediator.PublishAsync(navigate, cancellationToken);
|
||||
await publisher.PublishAsync(navigate, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,29 +2,26 @@
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public partial class NavigationViewModel :
|
||||
ObservableCollectionViewModel<INavigationViewModel>,
|
||||
public partial class NavigationViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
string text) :
|
||||
ObservableCollectionViewModel<INavigationViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer),
|
||||
INavigationViewModel
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string? text;
|
||||
|
||||
public NavigationViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer,
|
||||
string text) : base(serviceProvider, serviceFactory, mediator, disposer)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
private string? text = text;
|
||||
}
|
||||
|
||||
public partial class NavigationViewModel<TNavigationViewModel>(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
string text) :
|
||||
ObservableCollectionViewModel<TNavigationViewModel>(serviceProvider, serviceFactory, mediator, disposer),
|
||||
ObservableCollectionViewModel<TNavigationViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer),
|
||||
INavigationViewModel
|
||||
where TNavigationViewModel :
|
||||
INavigationViewModel
|
||||
|
||||
@@ -27,31 +27,33 @@ public partial class ObservableCollectionViewModel<TViewModel> :
|
||||
|
||||
public ObservableCollectionViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer)
|
||||
{
|
||||
ServiceProvider = serviceProvider;
|
||||
ServiceFactory = serviceFactory;
|
||||
Mediator = mediator;
|
||||
Publisher = publisher;
|
||||
Disposer = disposer;
|
||||
|
||||
mediator.Subscribe(this);
|
||||
subscriber.Add(this);
|
||||
|
||||
collection.CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
|
||||
public ObservableCollectionViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<TViewModel> items)
|
||||
{
|
||||
ServiceProvider = serviceProvider;
|
||||
ServiceFactory = serviceFactory;
|
||||
Mediator = mediator;
|
||||
Publisher = publisher;
|
||||
Disposer = disposer;
|
||||
|
||||
mediator.Subscribe(this);
|
||||
subscriber.Add(this);
|
||||
|
||||
collection.CollectionChanged += OnCollectionChanged;
|
||||
AddRange(items);
|
||||
@@ -74,14 +76,14 @@ public partial class ObservableCollectionViewModel<TViewModel> :
|
||||
|
||||
bool ICollection.IsSynchronized => false;
|
||||
|
||||
public IMediator Mediator { get; private set; }
|
||||
public IPublisher Publisher { get; private set; }
|
||||
|
||||
public IServiceFactory ServiceFactory { get; private set; }
|
||||
|
||||
object ICollection.SyncRoot => this;
|
||||
|
||||
public IServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
object ICollection.SyncRoot => this;
|
||||
|
||||
public TViewModel this[int index]
|
||||
{
|
||||
get => collection[index];
|
||||
@@ -374,7 +376,7 @@ public partial class ObservableCollectionViewModel<TViewModel> :
|
||||
|
||||
isInitialized = true;
|
||||
|
||||
await Mediator.PublishAsync<Enumerate<TViewModel>>();
|
||||
await Publisher.PublishAsync<Enumerate<TViewModel>>();
|
||||
await InitializeAsync();
|
||||
}
|
||||
|
||||
@@ -384,6 +386,7 @@ public partial class ObservableCollectionViewModel<TViewModel> :
|
||||
|
||||
public class ObservableCollectionViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableCollectionViewModel<IDisposable>(serviceProvider, serviceFactory, mediator, disposer);
|
||||
ObservableCollectionViewModel<IDisposable>(serviceProvider, serviceFactory, publisher, subscriber, disposer);
|
||||
@@ -6,7 +6,7 @@ namespace Hyperbar;
|
||||
|
||||
public class ObservableViewModel(IServiceProvider serviceProvider,
|
||||
IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
IDisposer disposer) :
|
||||
ObservableObject,
|
||||
IObservableViewModel
|
||||
@@ -16,9 +16,9 @@ public class ObservableViewModel(IServiceProvider serviceProvider,
|
||||
public IDisposer Disposer => disposer;
|
||||
|
||||
public ICommand InitializeCommand =>
|
||||
new AsyncRelayCommand(CoreInitializeAsync);
|
||||
new AsyncRelayCommand(CoreInitializeAsync);
|
||||
|
||||
public IMediator Mediator => mediator;
|
||||
public IPublisher Publisher => publisher;
|
||||
|
||||
public IServiceFactory ServiceFactory => serviceFactory;
|
||||
|
||||
|
||||
@@ -3,5 +3,4 @@
|
||||
public delegate Task<TResponse> HandlerDelegate<TMessage, TResponse>(TMessage message,
|
||||
CancellationToken cancellationToken)
|
||||
where TMessage :
|
||||
notnull,
|
||||
IMessage;
|
||||
@@ -1,27 +1,25 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public class HandlerWrapper<TRequest, TResponse>
|
||||
where TRequest :
|
||||
class,
|
||||
IRequest<TResponse>
|
||||
public class HandlerWrapper<TMessage, TReply>(IHandler<TMessage, TReply> handler,
|
||||
IEnumerable<IPipelineBehavior<TMessage, TReply>> pipelineBehaviours)
|
||||
where TMessage : class, IRequest<TReply>
|
||||
{
|
||||
private readonly HandlerDelegate<TRequest, TResponse> handler;
|
||||
private readonly IEnumerable<IPipelineBehavior<TMessage, TReply>> pipelineBehaviours =
|
||||
pipelineBehaviours.Reverse();
|
||||
|
||||
public HandlerWrapper(IHandler<TRequest, TResponse> concreteHandler,
|
||||
IEnumerable<IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours)
|
||||
public async Task<TReply> Handle(TMessage message, CancellationToken cancellationToken)
|
||||
{
|
||||
HandlerDelegate<TRequest, TResponse> handler = concreteHandler.Handle;
|
||||
foreach (IPipelineBehavior<TRequest, TResponse>? pipeline in pipelineBehaviours.Reverse())
|
||||
HandlerDelegate<TMessage, TReply> currentHandler = handler.Handle;
|
||||
foreach (IPipelineBehavior<TMessage, TReply> behavior in pipelineBehaviours)
|
||||
{
|
||||
HandlerDelegate<TRequest, TResponse> handlerCopy = handler;
|
||||
IPipelineBehavior<TRequest, TResponse> pipelineCopy = pipeline;
|
||||
|
||||
handler = (TRequest message, CancellationToken cancellationToken) =>
|
||||
pipelineCopy.Handle(message, handlerCopy, cancellationToken);
|
||||
HandlerDelegate<TMessage, TReply> previousHandler = currentHandler;
|
||||
currentHandler = async (msg, token) =>
|
||||
{
|
||||
return await behavior.Handle(msg, previousHandler, token);
|
||||
};
|
||||
}
|
||||
|
||||
this.handler = handler;
|
||||
return await currentHandler(message, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken);
|
||||
}
|
||||
@@ -2,41 +2,9 @@
|
||||
|
||||
public interface IMediator
|
||||
{
|
||||
Task PublishAsync<TNotification>(TNotification notification,
|
||||
object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification;
|
||||
|
||||
Task PublishAsync<TNotification>(object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new();
|
||||
|
||||
Task PublishAsync<TNotification>(TNotification notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification;
|
||||
|
||||
Task PublishAsync(object notification,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task PublishAsync(object notification,
|
||||
Func<Func<Task>, Task> marshal,
|
||||
object? key = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task PublishAsync<TNotification>(CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new();
|
||||
|
||||
Task<TResponse?> SendAsync<TResponse>(IRequest<TResponse> request,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<object?> SendAsync(object message, CancellationToken
|
||||
cancellationToken = default);
|
||||
|
||||
void Subscribe(object handler);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface INotification : IMessage;
|
||||
public interface INotification :
|
||||
IMessage;
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IPublisher
|
||||
{
|
||||
Task PublishAsync<TNotification>(TNotification notification,
|
||||
object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification;
|
||||
|
||||
Task PublishAsync<TNotification>(object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new();
|
||||
|
||||
Task PublishAsync<TNotification>(TNotification notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification;
|
||||
|
||||
Task PublishAsync(object notification,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task PublishAsync(object notification,
|
||||
Func<Func<Task>, Task> marshal,
|
||||
object? key = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task PublishAsync<TNotification>(CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface ISubscriber
|
||||
{
|
||||
void Remove(object subscriber);
|
||||
|
||||
void Add(object subscriber);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface ISubscriptionManager
|
||||
{
|
||||
IEnumerable<object?> GetHandlers(Type notificationType, object key);
|
||||
|
||||
void Remove(object subscriber);
|
||||
|
||||
void Add(object subscriber);
|
||||
}
|
||||
@@ -1,91 +1,8 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
namespace Hyperbar;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class Mediator(IServiceProvider provider,
|
||||
IDispatcher dispatcher) :
|
||||
public class Mediator(IServiceProvider provider) :
|
||||
IMediator
|
||||
{
|
||||
private readonly ConcurrentDictionary<object, List<object>> handlers = [];
|
||||
|
||||
public Task PublishAsync<TNotification>(object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new() => PublishAsync(new TNotification(), args => dispatcher.InvokeAsync(async () => await args()),
|
||||
key, cancellationToken);
|
||||
|
||||
public Task PublishAsync<TNotification>(TNotification notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification
|
||||
{
|
||||
return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()),
|
||||
null, cancellationToken);
|
||||
}
|
||||
|
||||
public Task PublishAsync<TNotification>(TNotification notification,
|
||||
object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification
|
||||
{
|
||||
return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()),
|
||||
key, cancellationToken);
|
||||
}
|
||||
|
||||
public Task PublishAsync(object notification,
|
||||
Func<Func<Task>, Task> marshal,
|
||||
object? key = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Type notificationType = notification.GetType();
|
||||
|
||||
List<object?> handlers = provider.GetServices(typeof(INotificationHandler<>)
|
||||
.MakeGenericType(notificationType)).ToList();
|
||||
|
||||
foreach (KeyValuePair<object, List<object>> subscriber in this.handlers)
|
||||
{
|
||||
if (subscriber.Key.Equals($"{key?.ToString()}:{notificationType}"))
|
||||
{
|
||||
handlers.AddRange(subscriber.Value);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (object? handler in handlers)
|
||||
{
|
||||
if (handler is not null)
|
||||
{
|
||||
Type? handlerType = handler.GetType();
|
||||
MethodInfo? handleMethod = handlerType.GetMethod("Handle",
|
||||
[notificationType, typeof(CancellationToken)]);
|
||||
|
||||
if (handleMethod is not null)
|
||||
{
|
||||
marshal(() => (Task)handleMethod.Invoke(handler, new object[] { notification,
|
||||
cancellationToken })!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task PublishAsync<TNotification>(CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new() => PublishAsync(new TNotification(), args => dispatcher.InvokeAsync(async () => await args()),
|
||||
null, cancellationToken);
|
||||
|
||||
public Task PublishAsync(object notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()),
|
||||
null, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<TResponse?> SendAsync<TResponse>(IRequest<TResponse> request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -121,44 +38,4 @@ public class Mediator(IServiceProvider provider,
|
||||
|
||||
return Task.FromResult<object?>(default);
|
||||
}
|
||||
|
||||
public void Subscribe(object handler)
|
||||
{
|
||||
Type handlerType = handler.GetType();
|
||||
object? key = GetKeyFromHandler(handlerType, handler);
|
||||
|
||||
foreach (Type interfaceType in GetNotificationHandlerInterfaces(handlerType))
|
||||
{
|
||||
if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType)
|
||||
{
|
||||
handlers.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", new List<object> { handler }, (value, collection) =>
|
||||
{
|
||||
collection.Add(handler);
|
||||
return collection;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object? GetKeyFromHandler(Type handlerType, object handler)
|
||||
{
|
||||
if (handlerType.GetCustomAttribute<NotificationHandlerAttribute>() is NotificationHandlerAttribute attribute)
|
||||
{
|
||||
if (handlerType.GetProperty($"{attribute.Key}") is PropertyInfo property
|
||||
&& property.GetValue(handler) is { } value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return attribute.Key;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IEnumerable<Type> GetNotificationHandlerInterfaces(Type handlerType) => handlerType.GetInterfaces()
|
||||
.Where(interfaceType => interfaceType.IsGenericType && interfaceType
|
||||
.GetGenericTypeDefinition() == typeof(INotificationHandler<>));
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class NotficationRelayHandler<TFromNotification, ToNotification>(IMediator mediator) :
|
||||
INotificationHandler<TFromNotification>,
|
||||
IHandler
|
||||
where TFromNotification :
|
||||
INotification
|
||||
where ToNotification :
|
||||
INotification, new()
|
||||
{
|
||||
private readonly IMediator mediator = mediator;
|
||||
|
||||
public Task Handle(TFromNotification notification, CancellationToken cancellationToken) =>
|
||||
mediator.PublishAsync<ToNotification>(cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class Publisher(ISubscriptionManager subscriptionManager,
|
||||
IServiceProvider provider,
|
||||
IDispatcher dispatcher) :
|
||||
IPublisher
|
||||
{
|
||||
public Task PublishAsync<TNotification>(object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new() => PublishAsync(new TNotification(), args => dispatcher.InvokeAsync(async () => await args()),
|
||||
key, cancellationToken);
|
||||
|
||||
public Task PublishAsync<TNotification>(TNotification notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification
|
||||
{
|
||||
return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()),
|
||||
null, cancellationToken);
|
||||
}
|
||||
|
||||
public Task PublishAsync<TNotification>(TNotification notification,
|
||||
object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification
|
||||
{
|
||||
return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()),
|
||||
key, cancellationToken);
|
||||
}
|
||||
|
||||
public Task PublishAsync(object notification,
|
||||
Func<Func<Task>, Task> marshal,
|
||||
object? key = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Type notificationType = notification.GetType();
|
||||
List<object?> handlers = provider.GetServices(typeof(INotificationHandler<>)
|
||||
.MakeGenericType(notificationType)).ToList();
|
||||
|
||||
foreach (object? handler in subscriptionManager.GetHandlers(notificationType,
|
||||
$"{key?.ToString()}:{notificationType}"))
|
||||
{
|
||||
handlers.Add(handler);
|
||||
}
|
||||
|
||||
foreach (object? handler in handlers)
|
||||
{
|
||||
if (handler is not null)
|
||||
{
|
||||
Type? handlerType = handler.GetType();
|
||||
MethodInfo? handleMethod = handlerType.GetMethod("Handle",
|
||||
[notificationType, typeof(CancellationToken)]);
|
||||
|
||||
if (handleMethod is not null)
|
||||
{
|
||||
marshal(() => (Task)handleMethod.Invoke(handler, new object[] { notification,
|
||||
cancellationToken })!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task PublishAsync<TNotification>(CancellationToken cancellationToken = default)
|
||||
where TNotification :
|
||||
INotification,
|
||||
new() => PublishAsync(new TNotification(), args => dispatcher.InvokeAsync(async () => await args()),
|
||||
null, cancellationToken);
|
||||
|
||||
public Task PublishAsync(object notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()),
|
||||
null, cancellationToken);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public class Subscriber(ISubscriptionManager subscriptionManager) :
|
||||
ISubscriber
|
||||
{
|
||||
public void Remove(object subscriber) =>
|
||||
subscriptionManager.Remove(subscriber);
|
||||
|
||||
public void Add(object subscriber) =>
|
||||
subscriptionManager.Add(subscriber);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public record Subscription(object Handler);
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class SubscriptionManager :
|
||||
ISubscriptionManager
|
||||
{
|
||||
private readonly ConcurrentDictionary<object, List<WeakReference>> subscriptions = new();
|
||||
|
||||
public IEnumerable<object?> GetHandlers(Type notificationType, object key)
|
||||
{
|
||||
if (subscriptions.TryGetValue($"{key?.ToString()}:{notificationType}",
|
||||
out List<WeakReference>? subscribers))
|
||||
{
|
||||
foreach (WeakReference weakRef in subscribers.ToArray())
|
||||
{
|
||||
object? target = weakRef.Target;
|
||||
if (target != null)
|
||||
{
|
||||
yield return target;
|
||||
}
|
||||
else
|
||||
{
|
||||
subscribers.Remove(weakRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(object subscriber)
|
||||
{
|
||||
Type handlerType = subscriber.GetType();
|
||||
object? key = GetKeyFromHandler(handlerType, subscriber);
|
||||
foreach (Type interfaceType in GetHandlerInterfaces(handlerType))
|
||||
{
|
||||
if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType)
|
||||
{
|
||||
if (subscriptions.TryGetValue($"{(key is not null ? $"{key}:" : "")}{argumentType}", out List<WeakReference>? subscribers))
|
||||
{
|
||||
for (int i = subscribers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!subscribers[i].IsAlive || subscribers[i].Target == subscriber)
|
||||
{
|
||||
subscribers.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(object subscriber)
|
||||
{
|
||||
Type handlerType = subscriber.GetType();
|
||||
object? key = GetKeyFromHandler(handlerType, subscriber);
|
||||
foreach (Type interfaceType in GetHandlerInterfaces(handlerType))
|
||||
{
|
||||
if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType)
|
||||
{
|
||||
subscriptions.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", _ => new List<WeakReference> { new WeakReference(subscriber) }, (_, collection) =>
|
||||
{
|
||||
collection.Add(new WeakReference(subscriber));
|
||||
return collection;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static object? GetKeyFromHandler(Type handlerType, object handler)
|
||||
{
|
||||
if (handlerType.GetCustomAttribute<NotificationHandlerAttribute>() is NotificationHandlerAttribute attribute)
|
||||
{
|
||||
if (handlerType.GetProperty($"{attribute.Key}") is PropertyInfo property
|
||||
&& property.GetValue(handler) is { } value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return attribute.Key;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IEnumerable<Type> GetHandlerInterfaces(Type handlerType) =>
|
||||
handlerType.GetInterfaces().Where(interfaceType => interfaceType.IsGenericType &&
|
||||
interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>));
|
||||
}
|
||||
Reference in New Issue
Block a user