Use dependency injection for all services

This commit is contained in:
Jack251970 2025-01-12 19:45:36 +08:00
parent 32cac76c82
commit 1b76a2bc1a
8 changed files with 65 additions and 43 deletions

View file

@ -54,6 +54,7 @@
<ItemGroup>
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
<PackageReference Include="BitFaster.Caching" Version="2.5.2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Fody" Version="6.5.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View file

@ -6,6 +6,7 @@ using System.Text;
using JetBrains.Annotations;
using Flow.Launcher.Infrastructure.UserSettings;
using ToolGood.Words.Pinyin;
using CommunityToolkit.Mvvm.DependencyInjection;
namespace Flow.Launcher.Infrastructure
{
@ -129,7 +130,12 @@ namespace Flow.Launcher.Infrastructure
private Settings _settings;
public void Initialize([NotNull] Settings settings)
public PinyinAlphabet()
{
Initialize(Ioc.Default.GetRequiredService<Settings>());
}
private void Initialize([NotNull] Settings settings)
{
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
}

View file

@ -1,4 +1,5 @@
using Flow.Launcher.Plugin.SharedModels;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Plugin.SharedModels;
using System;
using System.Collections.Generic;
using System.Linq;
@ -15,7 +16,7 @@ namespace Flow.Launcher.Infrastructure
public StringMatcher(IAlphabet alphabet = null)
{
_alphabet = alphabet;
_alphabet = Ioc.Default.GetRequiredService<IAlphabet>();
}
public static StringMatcher Instance { get; internal set; }

View file

@ -4,6 +4,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Core;
using Flow.Launcher.Core.Configuration;
using Flow.Launcher.Core.ExternalPlugins.Environments;
@ -18,23 +19,18 @@ using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
namespace Flow.Launcher
{
public partial class App : IDisposable, ISingleInstanceApp, IApp
public partial class App : IDisposable, ISingleInstanceApp
{
public IPublicAPI PublicAPI => API;
public static PublicAPIInstance API { get; private set; }
private const string Unique = "Flow.Launcher_Unique_Application_Mutex";
private static bool _disposed;
private Settings _settings;
private MainViewModel _mainVM;
private SettingWindowViewModel _settingsVM;
private readonly Updater _updater = new Updater(Flow.Launcher.Properties.Settings.Default.GithubRepo);
private readonly Portable _portable = new Portable();
private readonly PinyinAlphabet _alphabet = new PinyinAlphabet();
private StringMatcher _stringMatcher;
[STAThread]
public static void Main()
@ -53,37 +49,51 @@ namespace Flow.Launcher
{
await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
{
// Initialize settings
var storage = new FlowLauncherJsonStorage<Settings>();
_settings = storage.Load();
_settings.Initialize(storage);
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
_portable.PreStartCleanUpAfterPortabilityUpdate();
// Configure the dependency injection container
var host = Host.CreateDefaultBuilder()
.UseContentRoot(AppContext.BaseDirectory)
.ConfigureServices(services => services
.AddSingleton(_ => _settings)
.AddSingleton<Updater>()
.AddSingleton<Portable>()
.AddSingleton<SettingWindowViewModel>()
.AddSingleton<IAlphabet, PinyinAlphabet>()
.AddSingleton<StringMatcher>()
.AddSingleton<IPublicAPI, PublicAPIInstance>()
.AddSingleton<MainViewModel>()
).Build();
Ioc.Default.ConfigureServices(host.Services);
Log.Info(
"|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------");
Ioc.Default.GetRequiredService<Updater>().Initialize(Launcher.Properties.Settings.Default.GithubRepo);
Ioc.Default.GetRequiredService<Portable>().PreStartCleanUpAfterPortabilityUpdate();
Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------");
Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}");
RegisterAppDomainExceptions();
RegisterDispatcherUnhandledException();
var imageLoadertask = ImageLoader.InitializeAsync();
_settingsVM = new SettingWindowViewModel(_settings, _updater, _portable);
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
AbstractPluginEnvironment.PreStartPluginExecutablePathUpdate(_settings);
_alphabet.Initialize(_settings);
_stringMatcher = new StringMatcher(_alphabet);
StringMatcher.Instance = _stringMatcher;
_stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
var stringMatcher = Ioc.Default.GetRequiredService<StringMatcher>();
StringMatcher.Instance = stringMatcher;
stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
InternationalizationManager.Instance.Settings = _settings;
InternationalizationManager.Instance.ChangeLanguage(_settings.Language);
PluginManager.LoadPlugins(_settings.PluginSettings);
_mainVM = new MainViewModel(_settings);
API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet);
API = Ioc.Default.GetRequiredService<IPublicAPI>() as PublicAPIInstance;
Http.API = API;
Http.Proxy = _settings.Proxy;
@ -91,14 +101,15 @@ namespace Flow.Launcher
await PluginManager.InitializePluginsAsync(API);
await imageLoadertask;
var window = new MainWindow(_settings, _mainVM);
var mainVM = Ioc.Default.GetRequiredService<MainViewModel>();
var window = new MainWindow(_settings, mainVM);
Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}");
Current.MainWindow = window;
Current.MainWindow.Title = Constant.FlowLauncher;
HotKeyMapper.Initialize(_mainVM);
HotKeyMapper.Initialize(mainVM);
// main windows needs initialized before theme change because of blur settings
ThemeManager.Instance.Settings = _settings;
@ -147,11 +158,11 @@ namespace Flow.Launcher
{
// check update every 5 hours
var timer = new PeriodicTimer(TimeSpan.FromHours(5));
await _updater.UpdateAppAsync(API);
await Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync(API);
while (await timer.WaitForNextTickAsync())
// check updates on startup
await _updater.UpdateAppAsync(API);
await Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync(API);
}
});
}
@ -194,7 +205,7 @@ namespace Flow.Launcher
public void OnSecondAppStarted()
{
_mainVM.Show();
Ioc.Default.GetRequiredService<MainViewModel>().Show();
}
}
}

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
@ -83,12 +83,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Fody" Version="6.5.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="InputSimulator" Version="1.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.106">
<PrivateAssets>all</PrivateAssets>

View file

@ -25,7 +25,7 @@ using Flow.Launcher.Infrastructure.Storage;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Collections.Specialized;
using Flow.Launcher.Core;
using CommunityToolkit.Mvvm.DependencyInjection;
namespace Flow.Launcher
{
@ -33,15 +33,15 @@ namespace Flow.Launcher
{
private readonly SettingWindowViewModel _settingsVM;
private readonly MainViewModel _mainVM;
private readonly PinyinAlphabet _alphabet;
private readonly IAlphabet _alphabet;
#region Constructor
public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM, PinyinAlphabet alphabet)
public PublicAPIInstance()
{
_settingsVM = settingsVM;
_mainVM = mainVM;
_alphabet = alphabet;
_settingsVM = Ioc.Default.GetRequiredService<SettingWindowViewModel>();
_mainVM = Ioc.Default.GetRequiredService<MainViewModel>();
_alphabet = Ioc.Default.GetRequiredService<IAlphabet>();
GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback;
WebRequest.RegisterPrefix("data", new DataWebRequestFactory());
}

View file

@ -25,6 +25,7 @@ using System.Windows.Input;
using System.ComponentModel;
using Flow.Launcher.Infrastructure.Image;
using System.Windows.Media;
using CommunityToolkit.Mvvm.DependencyInjection;
namespace Flow.Launcher.ViewModel
{
@ -58,13 +59,13 @@ namespace Flow.Launcher.ViewModel
#region Constructor
public MainViewModel(Settings settings)
public MainViewModel()
{
_queryTextBeforeLeaveResults = "";
_queryText = "";
_lastQuery = new Query();
Settings = settings;
Settings = Ioc.Default.GetRequiredService<Settings>();
Settings.PropertyChanged += (_, args) =>
{
switch (args.PropertyName)

View file

@ -1,4 +1,5 @@
using Flow.Launcher.Core;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Core;
using Flow.Launcher.Core.Configuration;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
@ -13,11 +14,11 @@ public class SettingWindowViewModel : BaseModel
public Settings Settings { get; }
public SettingWindowViewModel(Settings settings, Updater updater, IPortable portable)
public SettingWindowViewModel()
{
Settings = settings;
Updater = updater;
Portable = portable;
Settings = Ioc.Default.GetRequiredService<Settings>();
Updater = Ioc.Default.GetRequiredService<Updater>();
Portable = Ioc.Default.GetRequiredService<Portable>();
}
public async void UpdateApp()