From c6618be0fcea0a46750d5adfae5ca78824c9c33a Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Wed, 17 Apr 2024 15:05:26 +0800 Subject: [PATCH] InitializeDataContext --- .../Extension/FrameworkElementExtension.cs | 17 ++++++ .../Snap.Hutao/Control/ScopedPage.cs | 14 +++-- .../Snap.Hutao/LaunchGameWindow.xaml.cs | 3 +- .../Announcement/AnnouncementService.cs | 54 ++++++++++--------- .../View/Card/AchievementCard.xaml.cs | 3 +- .../View/Card/DailyNoteCard.xaml.cs | 3 +- .../View/Card/GachaStatisticsCard.xaml.cs | 3 +- .../View/Card/LaunchGameCard.xaml.cs | 3 +- .../Snap.Hutao/View/Guide/GuideView.xaml.cs | 2 +- .../Snap.Hutao/View/MainView.xaml.cs | 6 +-- .../Snap.Hutao/View/TitleView.xaml.cs | 3 +- .../Snap.Hutao/View/UserView.xaml.cs | 3 +- 12 files changed, 76 insertions(+), 38 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Extension/FrameworkElementExtension.cs b/src/Snap.Hutao/Snap.Hutao/Control/Extension/FrameworkElementExtension.cs index 358294f7..a2ef684f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Extension/FrameworkElementExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Extension/FrameworkElementExtension.cs @@ -28,4 +28,21 @@ internal static class FrameworkElementExtension frameworkElement.IsRightTapEnabled = false; frameworkElement.IsTabStop = false; } + + public static void InitializeDataContext(this FrameworkElement frameworkElement, IServiceProvider? serviceProvider = default) + where TDataContext : class + { + IServiceProvider service = serviceProvider ?? Ioc.Default; + try + { + frameworkElement.DataContext = service.GetRequiredService(); + } + catch (Exception ex) + { + + ILogger? logger = service.GetRequiredService(typeof(ILogger<>).MakeGenericType([frameworkElement.GetType()])) as ILogger; + logger?.LogError(ex, "Failed to initialize DataContext"); + throw; + } + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs b/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs index 226884c5..8ff5df57 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs @@ -44,9 +44,17 @@ internal class ScopedPage : Page protected void InitializeWith() where TViewModel : class, IViewModel { - IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService(); - viewModel.CancellationToken = viewCancellationTokenSource.Token; - DataContext = viewModel; + try + { + IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService(); + viewModel.CancellationToken = viewCancellationTokenSource.Token; + DataContext = viewModel; + } + catch (Exception ex) + { + currentScope.ServiceProvider.GetRequiredService>().LogError(ex, "Failed to initialize view model."); + throw; + } } /// diff --git a/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs index 7143fa0e..ae9b83ff 100644 --- a/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml; +using Snap.Hutao.Control.Extension; using Snap.Hutao.Core.Windowing; using Snap.Hutao.ViewModel.Game; using Snap.Hutao.Win32.UI.WindowsAndMessaging; @@ -35,7 +36,7 @@ internal sealed partial class LaunchGameWindow : Window, IDisposable, IWindowOpt scope = serviceProvider.CreateScope(); windowOptions = new(this, DragableGrid, new(MaxWidth, MaxHeight)); this.InitializeController(serviceProvider); - RootGrid.DataContext = scope.ServiceProvider.GetRequiredService(); + RootGrid.InitializeDataContext(scope.ServiceProvider); } /// diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Announcement/AnnouncementService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Announcement/AnnouncementService.cs index cfcc4cd3..b2d79bb1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Announcement/AnnouncementService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Announcement/AnnouncementService.cs @@ -17,16 +17,15 @@ namespace Snap.Hutao.Service; /// [HighQuality] [ConstructorGenerated] -[Injection(InjectAs.Transient, typeof(IAnnouncementService))] +[Injection(InjectAs.Scoped, typeof(IAnnouncementService))] internal sealed partial class AnnouncementService : IAnnouncementService { private static readonly string CacheKey = $"{nameof(AnnouncementService)}.Cache.{nameof(AnnouncementWrapper)}"; - private readonly AnnouncementClient announcementClient; + private readonly IServiceScopeFactory serviceScopeFactory; private readonly ITaskContext taskContext; private readonly IMemoryCache memoryCache; - /// public async ValueTask GetAnnouncementWrapperAsync(string languageCode, Region region, CancellationToken cancellationToken = default) { // 缓存中存在记录,直接返回 @@ -36,29 +35,37 @@ internal sealed partial class AnnouncementService : IAnnouncementService } await taskContext.SwitchToBackgroundAsync(); - Response announcementWrapperResponse = await announcementClient - .GetAnnouncementsAsync(languageCode, region, cancellationToken) - .ConfigureAwait(false); - if (!announcementWrapperResponse.IsOk()) + List? contents; + AnnouncementWrapper wrapper; + using (IServiceScope scope = serviceScopeFactory.CreateScope()) { - return default!; + AnnouncementClient announcementClient = scope.ServiceProvider.GetRequiredService(); + + Response announcementWrapperResponse = await announcementClient + .GetAnnouncementsAsync(languageCode, region, cancellationToken) + .ConfigureAwait(false); + + if (!announcementWrapperResponse.IsOk()) + { + return default!; + } + + wrapper = announcementWrapperResponse.Data; + + Response> announcementContentResponse = await announcementClient + .GetAnnouncementContentsAsync(languageCode, region, cancellationToken) + .ConfigureAwait(false); + + if (!announcementContentResponse.IsOk()) + { + return default!; + } + + contents = announcementContentResponse.Data.List; } - AnnouncementWrapper wrapper = announcementWrapperResponse.Data; - Response> announcementContentResponse = await announcementClient - .GetAnnouncementContentsAsync(languageCode, region, cancellationToken) - .ConfigureAwait(false); - - if (!announcementContentResponse.IsOk()) - { - return default!; - } - - List contents = announcementContentResponse.Data.List; - - Dictionary contentMap = contents - .ToDictionary(id => id.AnnId, content => content.Content); + Dictionary contentMap = contents.ToDictionary(id => id.AnnId, content => content.Content); // 将活动公告置于前方 wrapper.List.Reverse(); @@ -75,8 +82,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService { foreach (ref readonly WebAnnouncement item in CollectionsMarshal.AsSpan(listWrapper.List)) { - contentMap.TryGetValue(item.AnnId, out string? rawContent); - item.Content = rawContent ?? string.Empty; + item.Content = contentMap.GetValueOrDefault(item.AnnId, string.Empty); } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/AchievementCard.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Card/AchievementCard.xaml.cs index 2cef88dc..cfdf65ee 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Card/AchievementCard.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/AchievementCard.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Extension; namespace Snap.Hutao.View.Card; @@ -15,7 +16,7 @@ internal sealed partial class AchievementCard : Button /// public AchievementCard() { - DataContext = Ioc.Default.GetRequiredService(); + this.InitializeDataContext(); InitializeComponent(); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/DailyNoteCard.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Card/DailyNoteCard.xaml.cs index 62f7311c..c73dd9f1 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Card/DailyNoteCard.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/DailyNoteCard.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Extension; namespace Snap.Hutao.View.Card; @@ -15,7 +16,7 @@ internal sealed partial class DailyNoteCard : Button /// public DailyNoteCard() { - DataContext = Ioc.Default.GetRequiredService(); + this.InitializeDataContext(); InitializeComponent(); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml.cs index 966f9998..190fcc8c 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Extension; namespace Snap.Hutao.View.Card; @@ -15,7 +16,7 @@ internal sealed partial class GachaStatisticsCard : Button /// public GachaStatisticsCard() { - DataContext = Ioc.Default.GetRequiredService(); + this.InitializeDataContext(); InitializeComponent(); } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml.cs index 832d6f1f..d2fc5cc4 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Extension; namespace Snap.Hutao.View.Card; @@ -15,7 +16,7 @@ internal sealed partial class LaunchGameCard : Button /// public LaunchGameCard() { - DataContext = Ioc.Default.GetRequiredService(); + this.InitializeDataContext(); InitializeComponent(); } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Guide/GuideView.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Guide/GuideView.xaml.cs index e0ccc278..0296865f 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Guide/GuideView.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Guide/GuideView.xaml.cs @@ -14,7 +14,7 @@ internal sealed partial class GuideView : UserControl { public GuideView() { + this.InitializeDataContext(); InitializeComponent(); - DataContext = this.ServiceProvider().GetRequiredService(); } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs index f13fc255..a9eb72e9 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Extension; using Snap.Hutao.Service.Navigation; using Snap.Hutao.View.Page; using Snap.Hutao.ViewModel; @@ -23,12 +24,11 @@ internal sealed partial class MainView : UserControl { IServiceProvider serviceProvider = Ioc.Default; - MainViewModel mainViewModel = serviceProvider.GetRequiredService(); + this.InitializeDataContext(serviceProvider); - DataContext = mainViewModel; InitializeComponent(); - mainViewModel.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter)); + (DataContext as MainViewModel)?.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter)); navigationService = serviceProvider.GetRequiredService(); if (navigationService is INavigationInitialization navigationInitialization) diff --git a/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs index e8c1b830..3ba335c1 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs @@ -3,6 +3,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Extension; using Snap.Hutao.ViewModel; namespace Snap.Hutao.View; @@ -15,7 +16,7 @@ internal sealed partial class TitleView : UserControl { public TitleView() { - DataContext = Ioc.Default.GetRequiredService(); + this.InitializeDataContext(); InitializeComponent(); } diff --git a/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml.cs index ad79147a..514addd7 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Extension; using Snap.Hutao.ViewModel.User; namespace Snap.Hutao.View; @@ -17,7 +18,7 @@ internal sealed partial class UserView : UserControl /// public UserView() { + this.InitializeDataContext(); InitializeComponent(); - DataContext = Ioc.Default.GetRequiredService(); } }