Skip to content

Commit bff0434

Browse files
authored
Use IoC Container (#258)
* Use IoC Container * Move Section classes to their own folder * Format code
1 parent 1536b0e commit bff0434

39 files changed

+360
-240
lines changed

src/Angor/Avalonia/AngorApp/App.axaml.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using AngorApp.Composition;
12
using AngorApp.Core;
23
using AngorApp.Sections.Shell;
34
using Avalonia;
@@ -17,15 +18,15 @@ public override void Initialize()
1718
.WriteTo.Console()
1819
.MinimumLevel.Debug()
1920
.CreateLogger();
20-
21+
2122
AvaloniaXamlLoader.Load(this);
2223
}
2324

2425
public override void OnFrameworkInitializationCompleted()
2526
{
2627
IconProvider.Current
2728
.Register<FontAwesomeIconProvider>();
28-
29+
2930
this.Connect(() => new MainView(), CompositionRoot.CreateMainViewModel, () => new MainWindow());
3031

3132
base.OnFrameworkInitializationCompleted();
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using AngorApp.Sections.Shell;
2+
using Microsoft.Extensions.DependencyInjection;
3+
4+
namespace AngorApp.Composition;
5+
6+
public static class CompositionRoot
7+
{
8+
public static IMainViewModel CreateMainViewModel(Control topLevelView)
9+
{
10+
var services = new ServiceCollection();
11+
12+
services
13+
.AddUIServices(topLevelView)
14+
.AddUIModelServices()
15+
.AddViewModels();
16+
17+
var serviceProvider = services.BuildServiceProvider();
18+
return serviceProvider.GetRequiredService<IMainViewModel>();
19+
}
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using AngorApp.Sections.Shell;
2+
using AngorApp.Sections.Shell.Sections;
3+
4+
namespace AngorApp.Composition;
5+
6+
public interface ISectionsFactory
7+
{
8+
IEnumerable<SectionBase> CreateSections();
9+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using AngorApp.Core;
2+
using AngorApp.Sections;
3+
using AngorApp.Sections.Founder;
4+
using AngorApp.Sections.Home;
5+
using AngorApp.Sections.Portfolio;
6+
using AngorApp.Sections.Shell;
7+
using AngorApp.Sections.Shell.Sections;
8+
using AngorApp.Sections.Wallet;
9+
using AngorApp.UI.Services;
10+
using Microsoft.Extensions.DependencyInjection;
11+
using Separator = AngorApp.Sections.Shell.Sections.Separator;
12+
13+
namespace AngorApp.Composition;
14+
15+
public class SectionsFactory(IServiceProvider serviceProvider) : ISectionsFactory
16+
{
17+
public IEnumerable<SectionBase> CreateSections()
18+
{
19+
return new SectionBase[]
20+
{
21+
Section.Create("Home", Get<IHomeSectionViewModel>(), "svg:/Assets/angor-icon.svg"),
22+
new Separator(),
23+
Section.Create("Wallet", Get<IWalletSectionViewModel>(), "fa-wallet"),
24+
Section.Create("Browse", Get<NavigationViewModel>(), "fa-magnifying-glass"),
25+
Section.Create("Portfolio", Get<IPortfolioSectionViewModel>(), "fa-hand-holding-dollar"),
26+
Section.Create("Founder", Get<IFounderSectionViewModel>(), "fa-money-bills"),
27+
new Separator(),
28+
Section.Create("Settings", () => new object(), "fa-gear"),
29+
new CommandSection("Angor Hub",
30+
ReactiveCommand.CreateFromTask(() =>
31+
Get<UIServices>()().LauncherService.LaunchUri(Constants.AngorHubUri)),
32+
"fa-magnifying-glass") { IsPrimary = false }
33+
};
34+
35+
Func<T> Get<T>() where T : notnull
36+
{
37+
return serviceProvider.GetRequiredService<T>;
38+
}
39+
}
40+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using Angor.UI.Model;
2+
using Angor.UI.Model.Implementation;
3+
using Angor.UI.Model.Implementation.Projects;
4+
using AngorApp.Core;
5+
using AngorApp.Design;
6+
using AngorApp.Sections;
7+
using AngorApp.Sections.Browse;
8+
using AngorApp.Sections.Founder;
9+
using AngorApp.Sections.Home;
10+
using AngorApp.Sections.Portfolio;
11+
using AngorApp.Sections.Shell;
12+
using AngorApp.Sections.Wallet;
13+
using AngorApp.UI.Services;
14+
using Avalonia.Controls.Notifications;
15+
using Microsoft.Extensions.DependencyInjection;
16+
using Zafiro.Avalonia.Controls.Navigation;
17+
using Zafiro.Avalonia.Dialogs;
18+
using Zafiro.Avalonia.Services;
19+
using Zafiro.UI;
20+
21+
namespace AngorApp.Composition;
22+
23+
public static class ServiceCollectionExtensions
24+
{
25+
public static IServiceCollection AddUIServices(this IServiceCollection services, Control parent)
26+
{
27+
var topLevel = TopLevel.GetTopLevel(parent);
28+
29+
return services
30+
.AddSingleton<ILauncherService>(_ => new LauncherService(topLevel!.Launcher))
31+
.AddSingleton<IDialog, DesktopDialog>()
32+
.AddSingleton<IActiveWallet, ActiveWallet>()
33+
.AddSingleton<INotificationService>(_ => new NotificationService(
34+
new WindowNotificationManager(topLevel)
35+
{
36+
Position = NotificationPosition.BottomRight
37+
}
38+
))
39+
.AddSingleton<UIServices>(sp => new UIServices(
40+
sp.GetRequiredService<ILauncherService>(),
41+
sp.GetRequiredService<IDialog>(),
42+
sp.GetRequiredService<INotificationService>(),
43+
sp.GetRequiredService<IActiveWallet>()
44+
));
45+
}
46+
47+
public static IServiceCollection AddUIModelServices(this IServiceCollection services)
48+
{
49+
return services
50+
.AddSingleton<IWalletProvider, WalletProviderDesign>()
51+
.AddSingleton<IWalletBuilder, WalletBuilderDesign>()
52+
.AddSingleton<IWalletFactory, WalletFactory>()
53+
.AddSingleton<IProjectService>(sp =>
54+
{
55+
var loggerFactory = LoggerConfig.CreateFactory();
56+
return new ProjectService(
57+
DependencyFactory.GetIndexerService(loggerFactory),
58+
DependencyFactory.GetRelayService(loggerFactory)
59+
);
60+
});
61+
}
62+
63+
private delegate IBrowseSectionViewModel BrowseSectionViewModelFactory(INavigator navigator);
64+
65+
public static IServiceCollection AddViewModels(this IServiceCollection services)
66+
{
67+
return services
68+
.AddTransient<BrowseSectionViewModelFactory>(sp =>
69+
navigator => ActivatorUtilities.CreateInstance<BrowseSectionViewModel>(sp, navigator))
70+
.AddTransient<NavigationViewModel>(sp =>
71+
new NavigationViewModel(navigator =>
72+
sp.GetRequiredService<BrowseSectionViewModelFactory>()(navigator)
73+
))
74+
.AddSingleton<ISectionsFactory, SectionsFactory>()
75+
.AddSingleton<Lazy<IMainViewModel>>(sp => new Lazy<IMainViewModel>(sp.GetRequiredService<IMainViewModel>))
76+
.AddTransient<IHomeSectionViewModel>(sp =>
77+
new HomeSectionViewModel(
78+
sp.GetRequiredService<IActiveWallet>(),
79+
sp.GetRequiredService<UIServices>(),
80+
() => sp.GetRequiredService<Lazy<IMainViewModel>>().Value
81+
))
82+
.AddTransient<IWalletSectionViewModel, WalletSectionViewModel>()
83+
84+
// // This registration could be maintained for alternative uses, but for navigation we will use the delegate
85+
.AddTransient<IBrowseSectionViewModel, BrowseSectionViewModel>()
86+
.AddTransient<IPortfolioSectionViewModel, PortfolioSectionViewModel>()
87+
.AddTransient<IFounderSectionViewModel, FounderSectionViewModel>()
88+
.AddSingleton<IMainViewModel>(sp =>
89+
new MainViewModel(
90+
sp.GetRequiredService<ISectionsFactory>().CreateSections(),
91+
sp.GetRequiredService<UIServices>()
92+
));
93+
}
94+
}

src/Angor/Avalonia/AngorApp/Core/CompositionRoot.cs

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/Angor/Avalonia/AngorApp/Core/LoggerConfiguration.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ public class LoggerConfig
88
{
99
public static ILoggerFactory CreateFactory()
1010
{
11-
// Configurar Serilog
1211
var logger = new LoggerConfiguration()
1312
.MinimumLevel.Debug()
1413
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
@@ -17,10 +16,8 @@ public static ILoggerFactory CreateFactory()
1716
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
1817
.CreateLogger();
1918

20-
// Crear el factory
2119
var factory = new LoggerFactory();
2220

23-
// Agregar Serilog al factory
2421
factory.AddSerilog(logger);
2522

2623
return factory;

src/Angor/Avalonia/AngorApp/Core/ViewLocator.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/Angor/Avalonia/AngorApp/Sections/Browse/BrowseSectionViewModel.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System.Reactive.Linq;
22
using Angor.UI.Model;
33
using AngorApp.Sections.Browse.ProjectLookup;
4-
using AngorApp.Services;
4+
using AngorApp.UI.Services;
55
using CSharpFunctionalExtensions;
66
using ReactiveUI.SourceGenerators;
77
using Zafiro.Avalonia.Controls.Navigation;
@@ -16,16 +16,18 @@ public partial class BrowseSectionViewModel : ReactiveObject, IBrowseSectionView
1616

1717
[ObservableAsProperty] private IList<IProjectViewModel>? projects;
1818

19-
public BrowseSectionViewModel(IWalletProvider walletProvider, IProjectService projectService, INavigator navigator, UIServices uiServices)
19+
public BrowseSectionViewModel(IWalletProvider walletProvider, IProjectService projectService, INavigator navigator,
20+
UIServices uiServices)
2021
{
2122
ProjectLookupViewModel = new ProjectLookupViewModel(projectService, walletProvider, navigator, uiServices);
22-
23+
2324
LoadLatestProjects = ReactiveCommand.CreateFromObservable(() => Observable.FromAsync(projectService.Latest)
2425
.Flatten()
2526
.Select(IProjectViewModel (project) => new ProjectViewModel(walletProvider, project, navigator, uiServices))
2627
.ToList());
2728

28-
OpenHub = ReactiveCommand.CreateFromTask(() => uiServices.LauncherService.LaunchUri(new Uri("https://www.angor.io")));
29+
OpenHub = ReactiveCommand.CreateFromTask(() =>
30+
uiServices.LauncherService.LaunchUri(new Uri("https://www.angor.io")));
2931
projectsHelper = LoadLatestProjects.ToProperty(this, x => x.Projects);
3032
LoadLatestProjects.Execute().Subscribe();
3133
}

src/Angor/Avalonia/AngorApp/Sections/Browse/BrowseSectionViewModelDesign.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using AngorApp.Sections.Browse.ProjectLookup;
33
using AngorApp.Sections.Shell;
44
using AngorApp.Sections.Wallet;
5-
using AngorApp.Services;
65
using CSharpFunctionalExtensions;
76

87
namespace AngorApp.Sections.Browse;

0 commit comments

Comments
 (0)