wip
This commit is contained in:
@@ -19,7 +19,7 @@ public class ContentControlHandler :
|
||||
control.Loaded -= HandleLoaded;
|
||||
if (control.DataContext is object content)
|
||||
{
|
||||
if (content is IInitializer initializer)
|
||||
if (content is IInitialization initializer)
|
||||
{
|
||||
await initializer.Initialize();
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public class ContentDialogHandler(IDispatcher dispatcher) :
|
||||
|
||||
// A hack to wait for the dialog to finish loading up to make it appear more responsive
|
||||
await Task.Delay(250);
|
||||
if (content is IInitializer initializer)
|
||||
if (content is IInitialization initializer)
|
||||
{
|
||||
await initializer.Initialize();
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ public class ContentTemplate :
|
||||
{
|
||||
if (observableViewModel.Provider is IServiceProvider provider)
|
||||
{
|
||||
IContentTemplateDescriptorProvider? contentTemplateProvider = provider.GetService<IContentTemplateDescriptorProvider>();
|
||||
INavigationRegion? viewModelContentBinder = provider.GetService<INavigationRegion>();
|
||||
Type itemType = item.GetType();
|
||||
|
||||
if (contentTemplateProvider?.Get(item.GetType().Name) is IContentTemplateDescriptor descriptor)
|
||||
if (provider.GetRequiredKeyedService<IContentTemplateDescriptor>(itemType.Name.Replace("ViewModel", ""))
|
||||
is IContentTemplateDescriptor descriptor)
|
||||
{
|
||||
if (provider.GetRequiredKeyedService(descriptor.TemplateType, descriptor.Key) is Control control)
|
||||
{
|
||||
@@ -28,7 +28,7 @@ public class ContentTemplate :
|
||||
control.Loaded -= HandleLoaded;
|
||||
if (control.DataContext is object content)
|
||||
{
|
||||
if (content is IInitializer initializer)
|
||||
if (content is IInitialization initializer)
|
||||
{
|
||||
await initializer.Initialize();
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class FrameHandler :
|
||||
sender.AddHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom);
|
||||
if (sender.DataContext is object content)
|
||||
{
|
||||
if (content is IInitializer initializer)
|
||||
if (content is IInitialization initializer)
|
||||
{
|
||||
await initializer.Initialize();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Toolkit.Foundation;
|
||||
using Toolkit.UI.Controls.Avalonia;
|
||||
|
||||
namespace Toolkit.Avalonia;
|
||||
|
||||
@@ -128,11 +129,11 @@ public static class IServiceCollectionExtensions
|
||||
services.AddTransient<IContentTemplate, ContentTemplate>();
|
||||
services.AddTransient<INavigationRegion, NavigationRegion>();
|
||||
|
||||
services.AddNavigateHandler<ClassicDesktopStyleApplicationHandler>();
|
||||
services.AddNavigateHandler<SingleViewApplicationHandler>();
|
||||
services.AddNavigateHandler<ContentControlHandler>();
|
||||
services.AddNavigateHandler<FrameHandler>();
|
||||
services.AddNavigateHandler<ContentDialogHandler>();
|
||||
services.AddHandler<ClassicDesktopStyleApplicationHandler>(nameof(IClassicDesktopStyleApplicationLifetime));
|
||||
services.AddHandler<SingleViewApplicationHandler>(nameof(ISingleViewApplicationLifetime));
|
||||
services.AddHandler<ContentControlHandler>(nameof(ContentControl));
|
||||
services.AddHandler<FrameHandler>(nameof(Frame));
|
||||
services.AddHandler<ContentDialogHandler>(nameof(ContentDialog));
|
||||
|
||||
services.AddScoped<INavigationRegionCollection, NavigationRegionCollection>(provider => new NavigationRegionCollection
|
||||
{
|
||||
@@ -144,15 +145,13 @@ public static class IServiceCollectionExtensions
|
||||
new ProxyServiceCollection<IComponentBuilder>(services =>
|
||||
{
|
||||
services.AddSingleton(provider.GetRequiredService<IDispatcher>());
|
||||
|
||||
services.AddTransient<IContentTemplateDescriptorProvider, ContentTemplateDescriptorProvider>();
|
||||
services.AddTransient<IContentTemplate, ContentTemplate>();
|
||||
|
||||
services.AddTransient<INavigationRegion, NavigationRegion>();
|
||||
|
||||
services.AddNavigateHandler<ContentControlHandler>();
|
||||
services.AddNavigateHandler<FrameHandler>();
|
||||
services.AddNavigateHandler<ContentDialogHandler>();
|
||||
services.AddHandler<ContentControlHandler>(nameof(ContentControl));
|
||||
services.AddHandler<FrameHandler>(nameof(Frame));
|
||||
services.AddHandler<ContentDialogHandler>(nameof(ContentDialog));
|
||||
})));
|
||||
|
||||
return services;
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class AppService(IEnumerable<IInitializer> initializers,
|
||||
public class AppService(IEnumerable<IInitialization> initializers,
|
||||
IPublisher publisher) :
|
||||
IHostedService
|
||||
{
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (IInitializer initializer in initializers)
|
||||
foreach (IInitialization initializer in initializers)
|
||||
{
|
||||
await initializer.Initialize();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record ChangedEventArgs<TSender>(TSender? Sender = default);
|
||||
public record ChangedEventArgs<TSender>(TSender? Sender = default);
|
||||
|
||||
@@ -6,7 +6,7 @@ public partial class CommandValueViewModel<TValue>(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) :
|
||||
ValueViewModel<TValue>(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ public partial class CommandViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
|
||||
@@ -32,14 +32,13 @@ public class ComponentBuilder :
|
||||
services.AddScoped<SubscriptionCollection>();
|
||||
|
||||
services.AddTransient<IHandlerProvider, HandlerProvider>();
|
||||
services.AddScoped<ISubscription, Subscription>();
|
||||
|
||||
services.AddScoped<ISubscriber, Subscriber>();
|
||||
services.AddTransient<IPublisher, Publisher>();
|
||||
|
||||
services.AddTransient<IMediator, Mediator>();
|
||||
|
||||
services.AddTransient<IContentFactory, ContentFactory>();
|
||||
services.AddTransient<INavigationScope, NavigationScope>();
|
||||
|
||||
services.AddTransient<INavigationProvider, NavigationProvider>();
|
||||
services.AddScoped<INavigationRegionCollection, NavigationRegionCollection>();
|
||||
services.AddTransient<INavigationRegionProvider, NavigationRegionProvider>();
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, THe
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
THeader header,
|
||||
TDescription description,
|
||||
@@ -30,7 +30,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, TAc
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
TAction action,
|
||||
TConfiguration configuration,
|
||||
@@ -72,7 +72,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, TDe
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
TAction action,
|
||||
TDescription description,
|
||||
|
||||
@@ -4,7 +4,7 @@ using Microsoft.Extensions.Hosting;
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class ComponentHost(IServiceProvider services,
|
||||
IEnumerable<IInitializer> initializers,
|
||||
IEnumerable<IInitialization> initializers,
|
||||
IEnumerable<IHostedService> hostedServices) :
|
||||
IComponentHost
|
||||
{
|
||||
@@ -21,7 +21,7 @@ public class ComponentHost(IServiceProvider services,
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
foreach (IInitializer initializer in initializers)
|
||||
foreach (IInitialization initializer in initializers)
|
||||
{
|
||||
await initializer.Initialize();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ public class ComponentInitializer(IEnumerable<IComponent> components,
|
||||
IComponentHostCollection hosts,
|
||||
IComponentScopeCollection scopes,
|
||||
IServiceProvider provider) :
|
||||
IInitializer
|
||||
IInitialization
|
||||
{
|
||||
public async Task Initialize()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ public class ConfigurationInitializer<TConfiguration>(IConfigurationReader<TConf
|
||||
IConfigurationFactory<TConfiguration> factory,
|
||||
IPublisher publisher) :
|
||||
IConfigurationInitializer<TConfiguration>,
|
||||
IInitializer
|
||||
IInitialization
|
||||
where TConfiguration :
|
||||
class
|
||||
{
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class ContentFactory(IMediator mediator,
|
||||
IServiceProvider provider,
|
||||
IServiceFactory factory) : IContentFactory
|
||||
{
|
||||
public async Task<object?> CreateAsync(IContentTemplateDescriptor descriptor,
|
||||
object[] parameters)
|
||||
{
|
||||
Type createEventType = typeof(CreateEventArgs<>).MakeGenericType(descriptor.ContentType);
|
||||
|
||||
object? content = null;
|
||||
if (Activator.CreateInstance(createEventType, [null, parameters]) is object createEvent)
|
||||
{
|
||||
content = await mediator.Handle(descriptor.ContentType, createEvent, descriptor.Key);
|
||||
}
|
||||
|
||||
if (content is null)
|
||||
{
|
||||
if (parameters is { Length: > 0 })
|
||||
{
|
||||
content = factory.Create(descriptor.ContentType, args =>
|
||||
{
|
||||
if (args is IPostInitialization initialization)
|
||||
{
|
||||
initialization.PostInitialize();
|
||||
}
|
||||
}, parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
content = provider.GetRequiredKeyedService(descriptor.ContentType, args =>
|
||||
{
|
||||
if (args is IPostInitialization initialization)
|
||||
{
|
||||
initialization.PostInitialize();
|
||||
}
|
||||
}, descriptor.Key);
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class ContentTemplateDescriptorProvider(IEnumerable<IContentTemplateDescriptor> contentTemplates) :
|
||||
IContentTemplateDescriptorProvider
|
||||
{
|
||||
public IContentTemplateDescriptor? Get(object key)
|
||||
{
|
||||
if (contentTemplates.FirstOrDefault(x => x.Key.Equals(key) || x.Key.Equals($"{key}".Replace("ViewModel", "")))
|
||||
is IContentTemplateDescriptor viewModelTemplate)
|
||||
{
|
||||
return viewModelTemplate;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,9 @@ public class DefaultHostBuilder :
|
||||
services.AddScoped<SubscriptionCollection>();
|
||||
|
||||
services.AddTransient<IHandlerProvider, HandlerProvider>();
|
||||
services.AddTransient<ISubscription, Subscription>();
|
||||
services.AddTransient<ISubscriber, Subscriber>();
|
||||
|
||||
services.AddTransient<ISubscription, Subscription>();
|
||||
services.AddTransient<ISubscriber, Subscriber>();
|
||||
|
||||
services.AddTransient<IPublisher, Publisher>();
|
||||
services.AddTransient<IMediator, Mediator>();
|
||||
@@ -45,9 +45,7 @@ public class DefaultHostBuilder :
|
||||
services.AddScoped<IProxyService<IComponentHostCollection>>(provider =>
|
||||
new ProxyService<IComponentHostCollection>(provider.GetRequiredService<IComponentHostCollection>()));
|
||||
|
||||
services.AddTransient<IContentTemplateDescriptorProvider, ContentTemplateDescriptorProvider>();
|
||||
|
||||
services.AddTransient<INavigationProvider, NavigationProvider>();
|
||||
services.AddTransient<IContentFactory, ContentFactory>();
|
||||
|
||||
services.AddScoped<INavigationRegionCollection, NavigationRegionCollection>();
|
||||
services.AddTransient<INavigationRegionProvider, NavigationRegionProvider>();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface IConfigurationChanged<TConfiguration> :
|
||||
IInitializer;
|
||||
IInitialization;
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
namespace Toolkit.Foundation
|
||||
{
|
||||
public interface IContentFactory
|
||||
{
|
||||
Task<object?> CreateAsync(IContentTemplateDescriptor descriptor, object[] resolvedArguments);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface IContentTemplateDescriptorProvider
|
||||
{
|
||||
IContentTemplateDescriptor? Get(object key);
|
||||
}
|
||||
@@ -156,7 +156,7 @@ public static class IHostBuilderExtension
|
||||
services.TryAddKeyedTransient<IConfigurationFactory<TConfiguration>>(section, (provider, key) =>
|
||||
new ConfigurationFactory<TConfiguration>(() => defaultConfiguration ?? provider.GetRequiredKeyedService<TConfiguration>(key)));
|
||||
|
||||
services.AddTransient<IInitializer, ConfigurationInitializer<TConfiguration>>(provider =>
|
||||
services.AddTransient<IInitialization, ConfigurationInitializer<TConfiguration>>(provider =>
|
||||
new ConfigurationInitializer<TConfiguration>(provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(section),
|
||||
provider.GetRequiredKeyedService<IConfigurationWriter<TConfiguration>>(section),
|
||||
provider.GetRequiredKeyedService<IConfigurationFactory<TConfiguration>>(section),
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface IInitializer
|
||||
public interface IInitialization
|
||||
{
|
||||
Task Initialize();
|
||||
}
|
||||
|
||||
public interface IInitializer<T>
|
||||
public interface IInitialization<T>
|
||||
{
|
||||
Task<T> Initialize();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface INavigationProvider
|
||||
{
|
||||
INavigation? Get(Type type);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface IPostInitialization
|
||||
{
|
||||
void PostInitialize();
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public static class IServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddCache<TKey, TValue>(this IServiceCollection services)
|
||||
@@ -132,31 +130,9 @@ public static class IServiceCollectionExtensions
|
||||
|
||||
public static IServiceCollection AddInitializer<TInitializer>(this IServiceCollection services)
|
||||
where TInitializer : class,
|
||||
IInitializer
|
||||
IInitialization
|
||||
{
|
||||
services.AddTransient<IInitializer, TInitializer>();
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddNavigateHandler<THandler>(this IServiceCollection services)
|
||||
where THandler : INavigateHandler,
|
||||
IHandler
|
||||
{
|
||||
IEnumerable<Type> contracts = typeof(THandler).GetInterfaces()
|
||||
.Where(x => x.Name == typeof(INavigateHandler<>).Name || x.Name == typeof(INavigateBackHandler<>).Name);
|
||||
|
||||
foreach (Type contract in contracts)
|
||||
{
|
||||
if (contract.GetGenericArguments() is { Length: 1 } arguments)
|
||||
{
|
||||
services.AddTransient<INavigation>(provider => new Navigation
|
||||
{
|
||||
Type = arguments[0]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
services.AddHandler<THandler>();
|
||||
services.AddTransient<IInitialization, TInitializer>();
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -205,7 +181,7 @@ public static class IServiceCollectionExtensions
|
||||
|
||||
services.Add(new ServiceDescriptor(viewType, key, viewType, serviceLifetime));
|
||||
|
||||
services.AddTransient<IContentTemplateDescriptor>(provider =>
|
||||
services.AddKeyedTransient<IContentTemplateDescriptor>(key, (provider, _) =>
|
||||
new ContentTemplateDescriptor(key, viewModelType, viewType, parameters));
|
||||
|
||||
return services;
|
||||
|
||||
@@ -7,5 +7,8 @@ public interface IServiceFactory
|
||||
TService Create<TService>(Action<TService> serviceDelegate,
|
||||
params object?[]? parameters);
|
||||
|
||||
object Create(Type type, Action<object> serviceDelegate,
|
||||
params object?[]? parameters);
|
||||
|
||||
TService Create<TService>(params object?[]? parameters);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public static class IServiceProviderExtensions
|
||||
{
|
||||
public static object GetRequiredKeyedService(this IServiceProvider provider,
|
||||
Type serviceType,
|
||||
Action<object> serviceDelegate,
|
||||
object? serviceKey)
|
||||
{
|
||||
object service = provider.GetRequiredKeyedService(serviceType, serviceKey);
|
||||
serviceDelegate.Invoke(service);
|
||||
|
||||
return service;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface ISubscriber
|
||||
{
|
||||
void Subscribe(object subscriber);
|
||||
|
||||
void Unsubscribe(object subscriber);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface ISubscriberRequired
|
||||
{
|
||||
ISubscriber Subscription { get; }
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface ISubscription
|
||||
{
|
||||
void Add(object subscriber);
|
||||
|
||||
void Remove(object subscriber);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface ISubscriptionRequired
|
||||
{
|
||||
ISubscription Subscription { get; }
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class NavigationProvider(IEnumerable<INavigation> navigations) :
|
||||
INavigationProvider
|
||||
{
|
||||
public INavigation? Get(Type type)
|
||||
{
|
||||
if (navigations.FirstOrDefault(x => type == x.Type ||
|
||||
type.BaseType == x.Type) is INavigation navigation)
|
||||
{
|
||||
return navigation;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class NavigationRegionProvider(INavigationRegionCollection contexts) :
|
||||
public class NavigationRegionProvider(INavigationRegionCollection collection) :
|
||||
INavigationRegionProvider
|
||||
{
|
||||
public object? Get(object key) =>
|
||||
contexts.TryGetValue(key, out object? target) ? target : default;
|
||||
collection.TryGetValue(key, out object? target) ? target : default;
|
||||
|
||||
public bool TryGet(object name,
|
||||
out object? value)
|
||||
{
|
||||
if (contexts.TryGetValue(name,
|
||||
if (collection.TryGetValue(name,
|
||||
out object? target))
|
||||
{
|
||||
value = target;
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class NavigationScope(IPublisher publisher,
|
||||
IMediator mediator,
|
||||
IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
INavigationProvider navigationProvider,
|
||||
public class NavigationScope(IServiceProvider provider,
|
||||
INavigationRegionProvider navigationRegionProvider,
|
||||
IContentTemplateDescriptorProvider contentTemplateDescriptorProvider) :
|
||||
IContentFactory contentFactory,
|
||||
IPublisher publisher) :
|
||||
INavigationScope
|
||||
{
|
||||
public async void Navigate(string route,
|
||||
@@ -30,7 +27,7 @@ public class NavigationScope(IPublisher publisher,
|
||||
{
|
||||
currentSegmentIndex++;
|
||||
|
||||
if (contentTemplateDescriptorProvider.Get(segment)
|
||||
if (provider.GetKeyedService<IContentTemplateDescriptor>(segment)
|
||||
is IContentTemplateDescriptor descriptor)
|
||||
{
|
||||
Dictionary<string, object>? arguments = parameters?.ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase) ?? [];
|
||||
@@ -42,14 +39,15 @@ public class NavigationScope(IPublisher publisher,
|
||||
.TryGetValue(x.Name, out object? argument) ? argument : default)
|
||||
.Where(argument => argument is not null)] : [];
|
||||
|
||||
if (provider.GetRequiredKeyedService(descriptor.TemplateType, segment) is object view)
|
||||
if (provider.GetRequiredKeyedService(descriptor.TemplateType, descriptor.Key)
|
||||
is object template)
|
||||
{
|
||||
if (region is not null)
|
||||
{
|
||||
switch (region)
|
||||
{
|
||||
case "self":
|
||||
region = view;
|
||||
region = template;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -64,38 +62,18 @@ public class NavigationScope(IPublisher publisher,
|
||||
|
||||
if (region is not null)
|
||||
{
|
||||
Type createEventType = typeof(CreateEventArgs<>).MakeGenericType(descriptor.ContentType);
|
||||
|
||||
object? content = null;
|
||||
if (Activator.CreateInstance(createEventType, [null, resolvedArguments]) is object createEvent)
|
||||
{
|
||||
content = await mediator.Handle(descriptor.ContentType, createEvent, descriptor.Key);
|
||||
}
|
||||
|
||||
if (content is null)
|
||||
{
|
||||
if (resolvedArguments is { Length: > 0 })
|
||||
{
|
||||
content = factory.Create(descriptor.ContentType, resolvedArguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
content = provider.GetRequiredKeyedService(descriptor.ContentType, segment);
|
||||
}
|
||||
}
|
||||
|
||||
object? content = await contentFactory.CreateAsync(descriptor, resolvedArguments);
|
||||
if (content is not null)
|
||||
{
|
||||
if (navigationProvider.Get(region is Type type ? type : region.GetType()) is INavigation navigation)
|
||||
Type navigationType = region is Type type ? type : region.GetType();
|
||||
Type navigateEventType = typeof(NavigateEventArgs<>).MakeGenericType(navigationType);
|
||||
if (Activator.CreateInstance(navigateEventType, [region, template, content, sender, parameters])
|
||||
is object navigateEvent)
|
||||
{
|
||||
Type navigateEventType = typeof(NavigateEventArgs<>).MakeGenericType(navigation.Type);
|
||||
if (Activator.CreateInstance(navigateEventType, [region, view, content, sender, parameters]) is object navigateEvent)
|
||||
publisher.Publish(navigateEvent, navigationType.Name);
|
||||
if (currentSegmentIndex == segmentCount)
|
||||
{
|
||||
publisher.Publish(navigateEvent);
|
||||
if (currentSegmentIndex == segmentCount)
|
||||
{
|
||||
navigated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
navigated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,14 +92,11 @@ public class NavigationScope(IPublisher publisher,
|
||||
|
||||
if (region is not null)
|
||||
{
|
||||
if (navigationProvider.Get(region is Type type ? type : region.GetType())
|
||||
is INavigation navigation)
|
||||
Type navigationType = region is Type type ? type : region.GetType();
|
||||
Type navigateType = typeof(NavigateBackEventArgs<>).MakeGenericType(navigationType);
|
||||
if (Activator.CreateInstance(navigateType, [region]) is object navigate)
|
||||
{
|
||||
Type navigateType = typeof(NavigateBackEventArgs<>).MakeGenericType(navigation.Type);
|
||||
if (Activator.CreateInstance(navigateType, [region]) is object navigate)
|
||||
{
|
||||
publisher.Publish(navigate);
|
||||
}
|
||||
publisher.Publish(navigate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
|
||||
public class NavigationTargetAttribute(string name) :
|
||||
Attribute
|
||||
{
|
||||
public string Name => name;
|
||||
}
|
||||
@@ -2,11 +2,18 @@
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public partial class Observable :
|
||||
public partial class Observable(IServiceProvider
|
||||
provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableObject,
|
||||
IObservableViewModel,
|
||||
IActivityIndicator,
|
||||
IInitializer,
|
||||
IPostInitialization,
|
||||
IInitialization,
|
||||
IActivated,
|
||||
IDeactivating,
|
||||
IDeactivated,
|
||||
@@ -20,40 +27,25 @@ public partial class Observable :
|
||||
{
|
||||
private readonly Dictionary<string, object> trackedProperties = [];
|
||||
|
||||
[ObservableProperty]
|
||||
private bool initialized;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool active;
|
||||
|
||||
public Observable(IServiceProvider
|
||||
provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer)
|
||||
{
|
||||
Provider = provider;
|
||||
Factory = factory;
|
||||
Mediator = mediator;
|
||||
Publisher = publisher;
|
||||
Disposer = disposer;
|
||||
|
||||
subscriber.Add(this);
|
||||
}
|
||||
[ObservableProperty]
|
||||
private bool initialized;
|
||||
private bool postInitialized;
|
||||
|
||||
public event EventHandler? DeactivateHandler;
|
||||
|
||||
public IDisposer Disposer { get; }
|
||||
public IDisposer Disposer { get; } = disposer;
|
||||
|
||||
public IServiceFactory Factory { get; }
|
||||
public IServiceFactory Factory { get; } = factory;
|
||||
|
||||
public IMediator Mediator { get; }
|
||||
public IMediator Mediator { get; } = mediator;
|
||||
|
||||
public IServiceProvider Provider { get; }
|
||||
public IServiceProvider Provider { get; } = provider;
|
||||
|
||||
public IPublisher Publisher { get; }
|
||||
public IPublisher Publisher { get; } = publisher;
|
||||
public ISubscriber Subscriber { get; } = subscriber;
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
@@ -95,6 +87,17 @@ public partial class Observable :
|
||||
public virtual Task OnDeactivating() =>
|
||||
Task.CompletedTask;
|
||||
|
||||
public virtual void PostInitialize()
|
||||
{
|
||||
if (postInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
postInitialized = true;
|
||||
Subscriber.Subscribe(this);
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
foreach (object trackedProperty in trackedProperties.Values)
|
||||
@@ -124,7 +127,7 @@ public partial class Observable<TValue> :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
TValue value) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
@@ -154,7 +157,7 @@ public partial class Observable<TKey, TValue> :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
TKey key,
|
||||
TValue value) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
|
||||
@@ -9,7 +9,8 @@ namespace Toolkit.Foundation;
|
||||
public partial class ObservableCollection<TItem> :
|
||||
ObservableObject,
|
||||
IObservableCollectionViewModel<TItem>,
|
||||
IInitializer,
|
||||
IPostInitialization,
|
||||
IInitialization,
|
||||
IActivated,
|
||||
IDeactivating,
|
||||
IDeactivated,
|
||||
@@ -32,7 +33,7 @@ public partial class ObservableCollection<TItem> :
|
||||
INotificationHandler<MoveToEventArgs<TItem>>,
|
||||
INotificationHandler<ReplaceEventArgs<TItem>>,
|
||||
INotificationHandler<SelectionEventArgs<TItem>>
|
||||
where TItem : notnull,
|
||||
where TItem : notnull,
|
||||
IDisposable
|
||||
{
|
||||
private readonly System.Collections.ObjectModel.ObservableCollection<TItem> collection = [];
|
||||
@@ -52,6 +53,8 @@ public partial class ObservableCollection<TItem> :
|
||||
[ObservableProperty]
|
||||
private bool initialized;
|
||||
|
||||
private bool postInitialized;
|
||||
|
||||
[ObservableProperty]
|
||||
private TItem? selectedItem;
|
||||
|
||||
@@ -59,17 +62,16 @@ public partial class ObservableCollection<TItem> :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer)
|
||||
{
|
||||
Provider = provider;
|
||||
Factory = factory;
|
||||
Mediator = mediator;
|
||||
Publisher = publisher;
|
||||
Subscriber = subscriber;
|
||||
Disposer = disposer;
|
||||
|
||||
subscriber.Add(this);
|
||||
|
||||
dispatcher = Provider.GetRequiredService<IDispatcher>();
|
||||
collection.CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
@@ -78,7 +80,7 @@ public partial class ObservableCollection<TItem> :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<TItem> items)
|
||||
{
|
||||
@@ -86,10 +88,9 @@ public partial class ObservableCollection<TItem> :
|
||||
Factory = factory;
|
||||
Mediator = mediator;
|
||||
Publisher = publisher;
|
||||
Subscriber = subscriber;
|
||||
Disposer = disposer;
|
||||
|
||||
subscriber.Add(this);
|
||||
|
||||
dispatcher = Provider.GetRequiredService<IDispatcher>();
|
||||
collection.CollectionChanged += OnCollectionChanged;
|
||||
|
||||
@@ -117,6 +118,7 @@ public partial class ObservableCollection<TItem> :
|
||||
public IServiceProvider Provider { get; private set; }
|
||||
|
||||
public IPublisher Publisher { get; private set; }
|
||||
public ISubscriber Subscriber { get; }
|
||||
|
||||
object ICollection.SyncRoot => this;
|
||||
|
||||
@@ -149,18 +151,19 @@ public partial class ObservableCollection<TItem> :
|
||||
where T :
|
||||
TItem
|
||||
{
|
||||
T? item = Factory.Create<T>(parameters);
|
||||
T? item = Factory.Create<T>(args =>
|
||||
{
|
||||
if (args is IPostInitialization initialization)
|
||||
{
|
||||
initialization.PostInitialize();
|
||||
}
|
||||
}, parameters);
|
||||
|
||||
Add(item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public void Clear(Action<ObservableCollection<TItem>> factory)
|
||||
{
|
||||
Clear();
|
||||
factory.Invoke(this);
|
||||
}
|
||||
|
||||
public void Add(TItem item)
|
||||
{
|
||||
int index = collection.Count;
|
||||
@@ -200,6 +203,11 @@ public partial class ObservableCollection<TItem> :
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear(Action<ObservableCollection<TItem>> factory)
|
||||
{
|
||||
Clear();
|
||||
factory.Invoke(this);
|
||||
}
|
||||
public void Clear()
|
||||
{
|
||||
clearing = true;
|
||||
@@ -246,17 +254,6 @@ public partial class ObservableCollection<TItem> :
|
||||
Disposer.Dispose(this);
|
||||
}
|
||||
|
||||
public void Fetch(bool reset = false)
|
||||
{
|
||||
if (reset)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
SynchronizeExpression expression = BuildAggregateExpression();
|
||||
Publisher.PublishUI(expression.Value, expression.Key);
|
||||
}
|
||||
|
||||
public void Fetch(Func<SynchronizeExpression> aggregateDelegate,
|
||||
bool reset = false)
|
||||
{
|
||||
@@ -268,6 +265,7 @@ public partial class ObservableCollection<TItem> :
|
||||
SynchronizeExpression expression = aggregateDelegate.Invoke();
|
||||
Publisher.PublishUI(expression.Value, expression.Key);
|
||||
}
|
||||
|
||||
public IEnumerator<TItem> GetEnumerator() =>
|
||||
collection.GetEnumerator();
|
||||
|
||||
@@ -413,7 +411,7 @@ public partial class ObservableCollection<TItem> :
|
||||
}
|
||||
|
||||
Initialized = true;
|
||||
Fetch();
|
||||
Synchronize();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -423,14 +421,21 @@ public partial class ObservableCollection<TItem> :
|
||||
where T :
|
||||
TItem
|
||||
{
|
||||
T? item = Factory.Create<T>(parameters);
|
||||
T? item = Factory.Create<T>(args =>
|
||||
{
|
||||
if (args is IPostInitialization initialization)
|
||||
{
|
||||
initialization.PostInitialize();
|
||||
}
|
||||
}, parameters);
|
||||
|
||||
InsertItem(index, item);
|
||||
UpdateSelection(item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public void Insert(int index,
|
||||
public void Insert(int index,
|
||||
TItem item)
|
||||
{
|
||||
InsertItem(index, item);
|
||||
@@ -516,6 +521,17 @@ public partial class ObservableCollection<TItem> :
|
||||
public virtual Task OnDeactivating() =>
|
||||
Task.CompletedTask;
|
||||
|
||||
public virtual void PostInitialize()
|
||||
{
|
||||
if (postInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
postInitialized = true;
|
||||
Subscriber.Subscribe(this);
|
||||
}
|
||||
|
||||
public bool Remove(TItem item)
|
||||
{
|
||||
int index = collection.IndexOf(item);
|
||||
@@ -574,6 +590,16 @@ public partial class ObservableCollection<TItem> :
|
||||
}
|
||||
}
|
||||
|
||||
public void Synchronize(bool reset = false)
|
||||
{
|
||||
if (reset)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
SynchronizeExpression expression = BuildAggregateExpression();
|
||||
Publisher.PublishUI(expression.Value, expression.Key);
|
||||
}
|
||||
public void Track<T>(string propertyName, Func<T> getter, Action<T> setter)
|
||||
{
|
||||
if (!trackedProperties.ContainsKey(propertyName))
|
||||
@@ -657,7 +683,7 @@ public partial class ObservableCollection<TValue, TViewModel>(IServiceProvider p
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
TValue value) : ObservableCollection<TViewModel>(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
where TViewModel : notnull, IDisposable
|
||||
@@ -690,7 +716,7 @@ public partial class ObservableCollection<TViewModel, TKey, TValue> :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
TKey key,
|
||||
TValue value) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
@@ -703,7 +729,7 @@ public partial class ObservableCollection<TViewModel, TKey, TValue> :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<TViewModel> items,
|
||||
TKey key,
|
||||
@@ -728,7 +754,7 @@ public class ObservableCollection :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) : base(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
}
|
||||
@@ -737,7 +763,7 @@ public class ObservableCollection :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<IDisposable> items) : base(provider, factory, mediator, publisher, subscriber, disposer, items)
|
||||
{
|
||||
|
||||
@@ -17,4 +17,13 @@ public class ServiceFactory(Func<Type, object?[]?, object> factory) :
|
||||
|
||||
public object Create(Type type, params object?[]? parameters) =>
|
||||
factory(type, parameters);
|
||||
|
||||
public object Create(Type type, Action<object> serviceDelegate,
|
||||
params object?[]? parameters)
|
||||
{
|
||||
object service = factory(type, parameters);
|
||||
serviceDelegate.Invoke(service);
|
||||
|
||||
return service;
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class Subscription(SubscriptionCollection subscriptions,
|
||||
public class Subscriber(SubscriptionCollection subscriptions,
|
||||
IDisposer disposer) :
|
||||
ISubscription
|
||||
ISubscriber
|
||||
{
|
||||
public void Add(object subscriber)
|
||||
public void Subscribe(object subscriber)
|
||||
{
|
||||
Type handlerType = subscriber.GetType();
|
||||
|
||||
@@ -45,7 +45,7 @@ public class Subscription(SubscriptionCollection subscriptions,
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(object subscriber)
|
||||
public void Unsubscribe(object subscriber)
|
||||
{
|
||||
Type handlerType = subscriber.GetType();
|
||||
IDictionary<Type, List<object>> subscribers = GetSubscriptionKeys(subscriber);
|
||||
@@ -6,7 +6,7 @@ public partial class ValueViewModel<TValue>(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) :
|
||||
Observable(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user