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.Schemas;
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.FontAwesome;
using Serilog;
@@ -50,12 +57,46 @@ class Program
private static IServiceProvider BuildServices()
{
var builder = new ServiceCollection();
AddViews(builder);
AddViewModels(builder);
AddServices(builder);
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)
{
builder.AddSingleton<DialogService>();
@@ -67,7 +108,6 @@ class Program
.Add("Client"));
builder.AddLogging((builder) => builder.AddSerilog(EnableLoggerExtensions.Log(null)));
builder.AddSingleton<IDataTemplate>(new ViewLocator());
}
private static void AddViewModels(ServiceCollection builder)

View File

@@ -7,8 +7,6 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
namespace Needlework.Net
{
@@ -40,6 +38,8 @@ namespace Needlework.Net
.WithMetrics()
.Build();
private readonly Dictionary<Type, Func<Control>> _viewRegister = [];
public ViewLocator()
{
_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)
{
var name = data?.GetType().Name;
if (name is null)
if (!_viewRegister.TryGetValue(data!.GetType(), out var activator))
{
throw new Exception("Data type name is null.");
}
if (!name.Contains("ViewModel"))
{
throw new Exception("Data type name must end with 'ViewModel'.");
throw new Exception("Data type has no registered view activator.");
}
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);
if (isCold)
{
res ??= (Control)Activator.CreateInstance(type)!;
res ??= activator();
_controlCache.AddOrUpdate(data!, res);
}