Too much to name... but damn, it got where we are needed

This commit is contained in:
TheXamlGuy
2024-01-14 15:06:30 +00:00
parent 66f4bb8757
commit 1283e8ff58
59 changed files with 511 additions and 250 deletions
@@ -1,5 +1,5 @@
namespace Hyperbar;
public record KeyAcceleratorRequest(VirtualKey Key,
public record KeyAccelerator(VirtualKey Key,
VirtualKey[]? Modifiers = null) :
IRequest;
-3
View File
@@ -1,3 +0,0 @@
namespace Hyperbar;
public record ProcessRequest(string Process) : IRequest;
+3
View File
@@ -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
{
+12
View File
@@ -0,0 +1,12 @@
namespace Hyperbar;
public interface IFactory<TParameter, TService>
{
TService? Create(TParameter value);
}
public interface IFactory<TService>
{
TService? Create();
}
+1 -1
View File
@@ -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);
}
-6
View File
@@ -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;
}
}
-6
View File
@@ -1,6 +0,0 @@
namespace Hyperbar;
public interface IMappingHandler<TFrom, TTo> : IHandler
{
TTo Handle();
}
+12 -5
View File
@@ -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;
});
}
}
}
+4
View File
@@ -0,0 +1,4 @@
namespace Hyperbar;
public record Changed<TValue>(TValue? Value = default) : INotification;
+1 -1
View File
@@ -1,3 +1,3 @@
namespace Hyperbar;
public record Created<TValue>(TValue? Value = default) : INotification;
public record Created<TValue>(TValue Value) : INotification;
+11 -17
View File
@@ -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;
}
+5 -1
View File
@@ -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;
}
+12 -9
View File
@@ -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; }
+23
View File
@@ -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;
}