refactor: remove magic from view locator

This commit is contained in:
estrogen elf
2025-06-16 02:50:05 -05:00
parent e195665ab1
commit 5a4a2f05f3
2 changed files with 52 additions and 21 deletions

View File

@@ -12,6 +12,13 @@ using Needlework.Net.ViewModels.Pages.Endpoints;
using Needlework.Net.ViewModels.Pages.Home; using Needlework.Net.ViewModels.Pages.Home;
using Needlework.Net.ViewModels.Pages.Schemas; using Needlework.Net.ViewModels.Pages.Schemas;
using Needlework.Net.ViewModels.Pages.WebSocket; using Needlework.Net.ViewModels.Pages.WebSocket;
using Needlework.Net.Views.MainWindow;
using Needlework.Net.Views.Pages.About;
using Needlework.Net.Views.Pages.Console;
using Needlework.Net.Views.Pages.Endpoints;
using Needlework.Net.Views.Pages.Home;
using Needlework.Net.Views.Pages.Schemas;
using Needlework.Net.Views.Pages.WebSocket;
using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia;
using Projektanker.Icons.Avalonia.FontAwesome; using Projektanker.Icons.Avalonia.FontAwesome;
using Serilog; using Serilog;
@@ -50,12 +57,46 @@ class Program
private static IServiceProvider BuildServices() private static IServiceProvider BuildServices()
{ {
var builder = new ServiceCollection(); var builder = new ServiceCollection();
AddViews(builder);
AddViewModels(builder); AddViewModels(builder);
AddServices(builder); AddServices(builder);
return builder.BuildServiceProvider(); return builder.BuildServiceProvider();
} }
private static void AddViews(ServiceCollection builder)
{
var locator = new ViewLocator();
// MAIN WINDOW
locator.Register<NotificationViewModel>(() => new NotificationView());
locator.Register<SchemaSearchDetailsViewModel>(() => new SchemaSearchDetailsView());
locator.Register<SchemaViewModel>(() => new SchemaView());
// ABOUT
locator.Register<AboutViewModel>(() => new AboutView());
// CONSOLE
locator.Register<ConsoleViewModel>(() => new ConsoleView());
// ENDPOINTS
locator.Register<EndpointListViewModel>(() => new EndpointListView());
locator.Register<EndpointSearchDetailsViewModel>(() => new EndpointSearchDetailsView());
locator.Register<EndpointsViewModel>(() => new EndpointsView());
locator.Register<EndpointTabItemContentViewModel>(() => new EndpointTabItemContentView());
locator.Register<PathOperationViewModel>(() => new PathOperationView());
locator.Register<PluginViewModel>(() => new PluginView());
locator.Register<PropertyClassViewModel>(() => new PropertyClassView());
// HOME
locator.Register<HomeViewModel>(() => new HomeView());
locator.Register<LibraryViewModel>(() => new LibraryView());
// SCHEMAS
locator.Register<SchemasViewModel>(() => new SchemasView());
locator.Register<SchemaItemViewModel>(() => new SchemaItemView());
// WEBSOCKET
locator.Register<WebSocketViewModel>(() => new WebSocketView());
locator.Register<EventViewModel>(() => new EventView());
builder.AddSingleton<IDataTemplate>(locator);
}
private static void AddServices(ServiceCollection builder) private static void AddServices(ServiceCollection builder)
{ {
builder.AddSingleton<DialogService>(); builder.AddSingleton<DialogService>();
@@ -67,7 +108,6 @@ class Program
.Add("Client")); .Add("Client"));
builder.AddLogging((builder) => builder.AddSerilog(EnableLoggerExtensions.Log(null))); builder.AddLogging((builder) => builder.AddSerilog(EnableLoggerExtensions.Log(null)));
builder.AddSingleton<IDataTemplate>(new ViewLocator());
} }
private static void AddViewModels(ServiceCollection builder) private static void AddViewModels(ServiceCollection builder)

View File

@@ -7,8 +7,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
namespace Needlework.Net namespace Needlework.Net
{ {
@@ -40,6 +38,8 @@ namespace Needlework.Net
.WithMetrics() .WithMetrics()
.Build(); .Build();
private readonly Dictionary<Type, Func<Control>> _viewRegister = [];
public ViewLocator() public ViewLocator()
{ {
_controlCache.Events.Value!.ItemRemoved += (source, args) => _controlCache.Events.Value!.ItemRemoved += (source, args) =>
@@ -55,32 +55,23 @@ namespace Needlework.Net
}; };
} }
public void Register<T>(Func<Control> viewActivator)
where T : INotifyPropertyChanged
{
_viewRegister[typeof(T)] = viewActivator;
}
public Control Build(object? data) public Control Build(object? data)
{ {
var name = data?.GetType().Name; if (!_viewRegister.TryGetValue(data!.GetType(), out var activator))
if (name is null)
{ {
throw new Exception("Data type name is null."); throw new Exception("Data type has no registered view activator.");
}
if (!name.Contains("ViewModel"))
{
throw new Exception("Data type name must end with 'ViewModel'.");
} }
name = name.Replace("ViewModel", "View");
var type = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.Name == name)
.FirstOrDefault();
if (type is null)
{
throw new Exception("Data type has no view.");
}
bool isCold = !_controlCache.TryGet(data!, out var res); bool isCold = !_controlCache.TryGet(data!, out var res);
if (isCold) if (isCold)
{ {
res ??= (Control)Activator.CreateInstance(type)!; res ??= activator();
_controlCache.AddOrUpdate(data!, res); _controlCache.AddOrUpdate(data!, res);
} }