Too much to name... but damn, it got where we are needed
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public record KeyAcceleratorRequest(VirtualKey Key,
|
||||
public record KeyAccelerator(VirtualKey Key,
|
||||
VirtualKey[]? Modifiers = null) :
|
||||
IRequest;
|
||||
@@ -1,3 +0,0 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public record ProcessRequest(string Process) : IRequest;
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public record StartProcess(string Process) : IRequest;
|
||||
@@ -119,16 +119,23 @@ public static class IServiceCollectionExtensions
|
||||
where THandler :
|
||||
IHandler
|
||||
{
|
||||
if (typeof(THandler).GetInterface(typeof(INotificationHandler<>).Name) is { } notificationContract)
|
||||
if (typeof(THandler).GetInterfaces() is { } contracts)
|
||||
{
|
||||
if (notificationContract.GetGenericArguments() is { Length: 1 } arguments)
|
||||
foreach (Type contract in contracts)
|
||||
{
|
||||
Type notificationType = arguments[0];
|
||||
if (contract.Name == typeof(INotificationHandler<>).Name)
|
||||
{
|
||||
if (contract.GetGenericArguments() is { Length: 1 } arguments)
|
||||
{
|
||||
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),
|
||||
provider => provider.GetRequiredService<THandler>(), lifetime));
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof(THandler).GetInterface(typeof(IHandler<,>).Name) is { } requestContract)
|
||||
@@ -150,20 +157,6 @@ public static class IServiceCollectionExtensions
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof(THandler).GetInterface(typeof(IMappingHandler<,>).Name) is { } mappingContract)
|
||||
{
|
||||
if (mappingContract.GetGenericArguments() is { Length: 2 } arguments)
|
||||
{
|
||||
Type responseType = arguments[1];
|
||||
|
||||
services.AddTransient(typeof(THandler));
|
||||
services.AddTransient(responseType, provider =>
|
||||
{
|
||||
return ((dynamic)provider.GetRequiredService<THandler>()).Handle();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
public static IServiceCollection AddWidgetTemplate<TWidgetContent>(this IServiceCollection services)
|
||||
|
||||
@@ -4,13 +4,13 @@ using System.Reactive.Disposables;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class ViewModelCache<TKey, TViewModel>(IDisposer disposer) :
|
||||
IViewModelCache<TKey, TViewModel>
|
||||
public class Cache<TKey, TService>(IDisposer disposer) :
|
||||
ICache<TKey, TService>
|
||||
where TKey : notnull
|
||||
{
|
||||
private readonly IDictionary<TKey, TViewModel> cache = new Dictionary<TKey, TViewModel>();
|
||||
private readonly IDictionary<TKey, TService> cache = new Dictionary<TKey, TService>();
|
||||
|
||||
public TViewModel this[TKey key]
|
||||
public TService this[TKey key]
|
||||
{
|
||||
get => cache[key];
|
||||
set => cache[key] = value;
|
||||
@@ -18,13 +18,13 @@ public class ViewModelCache<TKey, TViewModel>(IDisposer disposer) :
|
||||
|
||||
public ICollection<TKey> Keys => cache.Keys;
|
||||
|
||||
public ICollection<TViewModel> Values => cache.Values;
|
||||
public ICollection<TService> Values => cache.Values;
|
||||
|
||||
public int Count => cache.Count;
|
||||
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public void Add(TKey key, TViewModel value)
|
||||
public void Add(TKey key, TService value)
|
||||
{
|
||||
disposer.Add(value!, Disposable.Create(() =>
|
||||
{
|
||||
@@ -34,14 +34,14 @@ public class ViewModelCache<TKey, TViewModel>(IDisposer disposer) :
|
||||
cache.Add(key, value);
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<TKey, TViewModel> item)
|
||||
public void Add(KeyValuePair<TKey, TService> item)
|
||||
{
|
||||
cache.Add(item);
|
||||
}
|
||||
|
||||
public void Clear() => cache.Clear();
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TViewModel> item)
|
||||
public bool Contains(KeyValuePair<TKey, TService> item)
|
||||
{
|
||||
return cache.Contains(item);
|
||||
}
|
||||
@@ -51,12 +51,12 @@ public class ViewModelCache<TKey, TViewModel>(IDisposer disposer) :
|
||||
return cache.ContainsKey(key);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<TKey, TViewModel>[] array, int arrayIndex)
|
||||
public void CopyTo(KeyValuePair<TKey, TService>[] array, int arrayIndex)
|
||||
{
|
||||
cache.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TViewModel>> GetEnumerator()
|
||||
public IEnumerator<KeyValuePair<TKey, TService>> GetEnumerator()
|
||||
{
|
||||
return cache.GetEnumerator();
|
||||
}
|
||||
@@ -66,12 +66,12 @@ public class ViewModelCache<TKey, TViewModel>(IDisposer disposer) :
|
||||
return cache.Remove(key);
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<TKey, TViewModel> item)
|
||||
public bool Remove(KeyValuePair<TKey, TService> item)
|
||||
{
|
||||
return cache.Remove(item);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TViewModel value)
|
||||
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TService value)
|
||||
{
|
||||
return cache.TryGetValue(key, out value);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IViewModelCache<TKey, TViewModel> :
|
||||
public interface ICache<TKey, TViewModel> :
|
||||
IDictionary<TKey, TViewModel>
|
||||
where TKey : notnull
|
||||
{
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IFactory<TParameter, TService>
|
||||
{
|
||||
TService? Create(TParameter value);
|
||||
}
|
||||
|
||||
|
||||
public interface IFactory<TService>
|
||||
{
|
||||
TService? Create();
|
||||
}
|
||||
@@ -6,4 +6,4 @@ public interface IServiceFactory
|
||||
params object?[] parameters);
|
||||
|
||||
TService Create<TService>(params object?[] parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IServiceScopeFactory<TService>
|
||||
{
|
||||
TService? Create(params object?[] parameters);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IServiceScopeProvider<TService>
|
||||
{
|
||||
bool TryGet(TService service, out IServiceScope? serviceScope);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IViewModelFactory<TParameter, TViewModel>
|
||||
{
|
||||
TViewModel? Create(TParameter value);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class ServiceScopeFactory<TService>(IServiceScopeFactory serviceScopeFactory,
|
||||
ConcurrentDictionary<TService, IServiceScope> services) :
|
||||
IServiceScopeFactory<TService>
|
||||
where TService : notnull
|
||||
{
|
||||
public TService? Create(params object?[] parameters)
|
||||
{
|
||||
if (serviceScopeFactory.CreateScope() is IServiceScope serviceScope)
|
||||
{
|
||||
if (serviceScope.ServiceProvider.GetService<IServiceFactory>() is IServiceFactory serviceFactory)
|
||||
{
|
||||
if (serviceFactory.Create<TService>(parameters) is TService service)
|
||||
{
|
||||
services.TryAdd(service, serviceScope);
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public class ServiceScopeProvider<TService>(ConcurrentDictionary<TService, IServiceScope> services) :
|
||||
IServiceScopeProvider<TService>
|
||||
where TService : notnull
|
||||
{
|
||||
public bool TryGet(TService service,
|
||||
out IServiceScope? serviceScope)
|
||||
{
|
||||
if (services.TryGetValue(service, out IServiceScope? value))
|
||||
{
|
||||
serviceScope = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
serviceScope = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IMappingHandler<TFrom, TTo> : IHandler
|
||||
{
|
||||
TTo Handle();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
@@ -8,7 +8,7 @@ public class Mediator(IServiceProvider provider) :
|
||||
{
|
||||
private readonly SynchronizationContext? context = SynchronizationContext.Current;
|
||||
|
||||
private readonly ConditionalWeakTable<Type, dynamic> subjects = [];
|
||||
private readonly ConcurrentDictionary<Type, List<dynamic>> subjects = [];
|
||||
|
||||
public ValueTask PublishAsync<TNotification>(TNotification notification,
|
||||
CancellationToken cancellationToken = default)
|
||||
@@ -18,11 +18,14 @@ public class Mediator(IServiceProvider provider) :
|
||||
List<INotificationHandler<TNotification>> handlers =
|
||||
provider.GetServices<INotificationHandler<TNotification>>().ToList();
|
||||
|
||||
foreach (KeyValuePair<Type, dynamic> handler in subjects)
|
||||
foreach (KeyValuePair<Type, List<dynamic>> handler in subjects)
|
||||
{
|
||||
if (handler.Key == typeof(TNotification))
|
||||
{
|
||||
handlers.Add(handler.Value);
|
||||
foreach (dynamic value in handler.Value)
|
||||
{
|
||||
handlers.Add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +83,11 @@ public class Mediator(IServiceProvider provider) :
|
||||
if (interfaceType.GetGenericArguments() is { Length: 1 } arguments)
|
||||
{
|
||||
Type notificationType = arguments[0];
|
||||
subjects.Add(notificationType, subject);
|
||||
subjects.AddOrUpdate(notificationType, [subject], (value, collection) =>
|
||||
{
|
||||
collection.Add(subject);
|
||||
return collection;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public record Changed<TValue>(TValue? Value = default) : INotification;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public record Created<TValue>(TValue? Value = default) : INotification;
|
||||
public record Created<TValue>(TValue Value) : INotification;
|
||||
@@ -19,6 +19,7 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
private readonly IDisposer disposer;
|
||||
private readonly IViewModelEnumerator<TItem>? enumerator;
|
||||
private readonly IServiceFactory serviceFactory;
|
||||
|
||||
public ObservableCollectionViewModel(IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer)
|
||||
@@ -138,7 +139,7 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
where T : TItem
|
||||
{
|
||||
T? item = serviceFactory.Create<T>(parameters);
|
||||
context?.Post(state => Add(item), null);
|
||||
Add(item);
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -155,20 +156,17 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
|
||||
public void Add(TItem item)
|
||||
{
|
||||
context?.Post(state =>
|
||||
disposer.Add(this, item);
|
||||
disposer.Add(item, Disposable.Create(item, args =>
|
||||
{
|
||||
disposer.Add(this, item);
|
||||
disposer.Add(item, Disposable.Create(item, args =>
|
||||
if (Contains(args))
|
||||
{
|
||||
if (Contains(args))
|
||||
{
|
||||
Remove(args);
|
||||
}
|
||||
}));
|
||||
Remove(args);
|
||||
}
|
||||
}));
|
||||
|
||||
int index = collection.Count;
|
||||
InsertItem(index, item);
|
||||
}, null);
|
||||
int index = collection.Count;
|
||||
InsertItem(index, item);
|
||||
}
|
||||
|
||||
int IList.Add(object? value)
|
||||
@@ -281,11 +279,7 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
int index = collection.IndexOf(item);
|
||||
if (index < 0) return false;
|
||||
|
||||
context?.Post(state =>
|
||||
{
|
||||
context?.Post(state => RemoveItem(index), null);
|
||||
|
||||
}, null);
|
||||
RemoveItem(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -8,12 +8,16 @@ public partial class WidgetButtonViewModel(IServiceFactory serviceFactory,
|
||||
IDisposer disposer,
|
||||
ITemplateFactory templateFactory,
|
||||
Guid guid = default,
|
||||
string? text = null,
|
||||
string? icon = null,
|
||||
RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory, guid)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private IRelayCommand? click = command;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? icon = icon;
|
||||
|
||||
[ObservableProperty]
|
||||
private IRelayCommand? click = command;
|
||||
private string? text = text;
|
||||
}
|
||||
@@ -3,29 +3,32 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public partial class WidgetComponentViewModel :
|
||||
ObservableViewModel,
|
||||
ObservableCollectionViewModel<IWidgetComponentViewModel>,
|
||||
IWidgetComponentViewModel,
|
||||
ITemplatedViewModel
|
||||
{
|
||||
private readonly IMediator mediator;
|
||||
private readonly IServiceFactory serviceFactory;
|
||||
|
||||
[ObservableProperty]
|
||||
private Guid id;
|
||||
|
||||
public WidgetComponentViewModel(IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer,
|
||||
ITemplateFactory templateFactory,
|
||||
IEnumerable<IWidgetComponentViewModel> items,
|
||||
Guid id = default) : base(serviceFactory, mediator, disposer, items)
|
||||
{
|
||||
this.id = id;
|
||||
TemplateFactory = templateFactory;
|
||||
}
|
||||
|
||||
public WidgetComponentViewModel(IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer,
|
||||
ITemplateFactory templateFactory,
|
||||
Guid id = default) : base(serviceFactory, mediator, disposer)
|
||||
{
|
||||
this.serviceFactory = serviceFactory;
|
||||
this.mediator = mediator;
|
||||
this.id = id;
|
||||
|
||||
TemplateFactory = templateFactory;
|
||||
|
||||
mediator.Subscribe(this);
|
||||
}
|
||||
|
||||
public ITemplateFactory TemplateFactory { get; private set; }
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public partial class WidgetMenuViewModel(IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer,
|
||||
ITemplateFactory templateFactory,
|
||||
Guid guid = default,
|
||||
string? text = null,
|
||||
string? icon = null,
|
||||
RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory, guid)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private IRelayCommand? click = command;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? icon = icon;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? text = text;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public partial class WidgetSplitButtonViewModel(IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer,
|
||||
ITemplateFactory templateFactory,
|
||||
IEnumerable<IWidgetComponentViewModel> items,
|
||||
Guid guid = default,
|
||||
string? text = null,
|
||||
string? icon = null,
|
||||
RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory, items, guid)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private IRelayCommand? click = command;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? icon = icon;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? text = text;
|
||||
}
|
||||
Reference in New Issue
Block a user