• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

なろうブックマーク分析用ツールのPrism+MAUIサンプル実装


Commit MetaInfo

Revisión9b22bbc5f4626c0ce4b6fd8a6aeaa795d4eb8e50 (tree)
Tiempo2022-08-25 06:35:28
Autoryoshy <yoshy.org.bitbucket@gz.j...>
Commiteryoshy

Log Message

[UPG] ObservableCollectionMod を CleanAuLait.ObservableCollectionMod に差し替え
[MOD] Service/Model/ViewModel の破棄処理が正しく行われるように改善
[CLEAN] コードクリーンナップ

Cambiar Resumen

Diferencia incremental

--- a/TestNarou2.Adaptor/Boundary/Gateway/ViewModel/IBookmarkCategoryViewModel.cs
+++ b/TestNarou2.Adaptor/Boundary/Gateway/ViewModel/IBookmarkCategoryViewModel.cs
@@ -12,7 +12,7 @@ namespace TestNarou2.Adaptor.Boundary.Gateway.ViewModel
1212 IAppWindowController WindowController { get; }
1313
1414 ReactiveProperty<IBookmarkCategoryRowViewModel> SelectedItem { get; }
15- ISynchronizedSingleView<BookmarkCategoryRow, IBookmarkCategoryRowViewModel> Rows { get; }
15+ INotifyCollectionChangedListSynchronizedSingleView<BookmarkCategoryRow, IBookmarkCategoryRowViewModel> Rows { get; }
1616
1717 BookmarkCategory Source { get; }
1818
--- a/TestNarou2.Adaptor/Boundary/Gateway/ViewModel/IBookmarkDetailListViewModel.cs
+++ b/TestNarou2.Adaptor/Boundary/Gateway/ViewModel/IBookmarkDetailListViewModel.cs
@@ -15,7 +15,7 @@ namespace TestNarou2.Adaptor.Boundary.Gateway.ViewModel
1515 internal static readonly Uri URI = new("BookmarkDetailListView", UriKind.Relative);
1616
1717 ReactiveProperty<IBookmarkDetailListRowViewModel> SelectedItem { get; }
18- ISynchronizedSingleView<BookmarkDetailListRow, IBookmarkDetailListRowViewModel> Rows { get; }
18+ INotifyCollectionChangedListSynchronizedSingleView<BookmarkDetailListRow, IBookmarkDetailListRowViewModel> Rows { get; }
1919
2020 ReactiveCommand CommandOpenBookmark { get; }
2121 BookmarkDetailList Source { get; }
--- a/TestNarou2.Adaptor/Gateway/ViewModel/BookmarkCategoryViewModel.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/BookmarkCategoryViewModel.cs
@@ -1,4 +1,5 @@
1-using CleanAuLait.ObservableCollectionsMod;
1+using CleanAuLait.Core.Log;
2+using CleanAuLait.ObservableCollectionsMod;
23 using NLog;
34 using Reactive.Bindings;
45 using Reactive.Bindings.Extensions;
@@ -14,7 +15,7 @@ using TestNarou2.Domain.Model.Entity.Child;
1415 namespace TestNarou2.Adaptor.Gateway.ViewModel
1516 {
1617 internal class BookmarkCategoryViewModel
17- : IBookmarkCategoryViewModel, INotifyPropertyChanged, IDestructible
18+ : IBookmarkCategoryViewModel, INotifyPropertyChanged, IDestructible, IDisposable
1819 {
1920 private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
2021
@@ -24,14 +25,16 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
2425
2526 public ReactiveProperty<IBookmarkCategoryRowViewModel> SelectedItem { get; }
2627
27- public ISynchronizedSingleView<BookmarkCategoryRow, IBookmarkCategoryRowViewModel> Rows { get; private set; } = null;
28+ public INotifyCollectionChangedListSynchronizedSingleView<BookmarkCategoryRow, IBookmarkCategoryRowViewModel> Rows { get; private set; } = null;
2829
2930 public BookmarkCategory Source { get; private set; }
3031
3132 public IAppWindowController WindowController { get; }
3233
3334 private readonly IBookmarkCategoryRowViewModelTranslator vmTranslator;
35+
3436 private readonly CompositeDisposable disposables = new();
37+ private bool disposedValue;
3538
3639 public BookmarkCategoryViewModel(
3740 IAppWindowController wc,
@@ -44,6 +47,8 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
4447 this.SelectedItem.Subscribe(OnSelectedItemChanged).AddTo(disposables);
4548 }
4649
50+ #region event handler
51+
4752 private void OnSelectedItemChanged(IBookmarkCategoryRowViewModel row)
4853 {
4954 if (row == null)
@@ -53,30 +58,69 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
5358 this.WindowController.NavigateBookmarkListView(row.Index);
5459 }
5560
61+ #endregion
62+
63+ #region vm operation
64+
5665 public void SynchronizeWith(BookmarkCategory source)
5766 {
58- if (this.Rows != null)
67+ if (this.Source == null)
5968 {
60- this.Rows.Dispose();
61- this.disposables.Remove(this.Rows);
69+ this.Rows = source.Rows
70+ .ToSynchronizedCoupleView(r => this.vmTranslator.Translate(r, this))
71+ .ToSynchronizedSingleView()
72+ .WithINotifyCollectionChangedList()
73+ .AddTo(disposables);
74+
75+ logger.Trace("BookmarkCategoryViewModel.SynchronizeWith: source [{0}], collection view [{1}]",
76+ source.ToHashString(), this.Rows.GetType().FullName);
77+
78+ this.Source = source;
79+
80+ // after transitioning to the bookmark page, the first category must be selected.
81+ if (source.Rows.Count() > 0)
82+ {
83+ this.SelectedItem.Value = this.Rows.ElementAt(0);
84+ }
6285 }
86+ else
87+ {
88+ logger.Trace("BookmarkCategoryViewModel.SynchronizeWith: viewmodel already synchronized to model [{0}]",
89+ this.Source.ToHashString());
90+ }
91+ }
6392
64- this.Rows = source.Rows
65- .ToSynchronizedCoupleView(r => this.vmTranslator.Translate(r, this))
66- .ToSynchronizedSingleView()
67- .AddTo(disposables);
68-
69- logger.Trace("BookmarkCategoryViewModel.SynchronizeWith: collection view [{0}]", this.Rows.GetType().FullName);
93+ #endregion
7094
71- this.Source = source;
95+ #region IDestructible, IDisposable
7296
73- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Rows)));
97+ public void Destroy()
98+ {
99+ this.Dispose();
74100 }
75101
76- public void Destroy()
102+ protected virtual void Dispose(bool disposing)
77103 {
104+ if (!disposedValue)
105+ {
106+ if (disposing)
107+ {
78108 this.disposables.Dispose();
109+
110+ logger.Trace("BookmarkCategoryViewModel disposed.");
111+ }
112+
113+ disposedValue = true;
114+ }
79115 }
80116
117+ public void Dispose()
118+ {
119+ Dispose(disposing: true);
120+ GC.SuppressFinalize(this);
121+ }
122+
123+ #endregion
124+
81125 }
82126 }
--- a/TestNarou2.Adaptor/Gateway/ViewModel/BookmarkDetailListViewModel.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/BookmarkDetailListViewModel.cs
@@ -1,4 +1,5 @@
1-using CleanAuLait.ObservableCollectionsMod;
1+using CleanAuLait.Core.Log;
2+using CleanAuLait.ObservableCollectionsMod;
23 using NLog;
34 using Reactive.Bindings;
45 using Reactive.Bindings.Extensions;
@@ -15,7 +16,7 @@ using TestNarou2.Domain.Model.Entity.Child;
1516 namespace TestNarou2.Adaptor.Gateway.ViewModel
1617 {
1718 internal class BookmarkDetailListViewModel
18- : IBookmarkDetailListViewModel, INotifyPropertyChanged, IDestructible
19+ : IBookmarkDetailListViewModel, INotifyPropertyChanged, IDestructible, IDisposable
1920 {
2021 private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
2122
@@ -25,7 +26,7 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
2526
2627 public ReactiveProperty<IBookmarkDetailListRowViewModel> SelectedItem { get; }
2728
28- public ISynchronizedSingleView<BookmarkDetailListRow, IBookmarkDetailListRowViewModel> Rows { get; private set; } = null;
29+ public INotifyCollectionChangedListSynchronizedSingleView<BookmarkDetailListRow, IBookmarkDetailListRowViewModel> Rows { get; private set; } = null;
2930
3031 public ReactiveCommand CommandOpenBookmark { get; }
3132
@@ -34,9 +35,10 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
3435 private IAppWindowController WindowController { get; }
3536
3637 private IBookmarkDetailListRowViewModel selectedRow;
37-
3838 private readonly IBookmarkDetailListRowViewModelTranslator vmTranslator;
39+
3940 private readonly CompositeDisposable disposables = new();
41+ private bool disposedValue;
4042
4143 public BookmarkDetailListViewModel(
4244 IAppWindowController wc,
@@ -52,6 +54,8 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
5254 .WithSubscribe(OpenBookmark).AddTo(disposables);
5355 }
5456
57+ #region event handler
58+
5559 private void OnSelectedItemChanged(IBookmarkDetailListRowViewModel selectedRow)
5660 {
5761 this.selectedRow = selectedRow;
@@ -59,44 +63,77 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
5963
6064 private void OpenBookmark()
6165 {
66+ logger.Trace("OpenBookmark: {0}", this.selectedRow?.NCode ?? "item not selected");
67+
6268 if (this.selectedRow == null)
6369 {
6470 return;
6571 }
6672
67- logger.Trace("OpenBookmark: {0}", this.selectedRow.NCode);
68-
6973 // TODO Service
7074
7175 string url = "https://ncode.syosetu.com/" + this.selectedRow.NCode.ToLower();
7276 Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
7377 }
7478
79+ #endregion
80+
81+ #region vm operation
82+
7583 public void SynchronizeWith(BookmarkDetailList source)
7684 {
77- if (this.Rows != null)
85+ if (this.Source == null)
7886 {
79- this.Rows.Dispose();
80- this.disposables.Remove(this.Rows);
81- }
82-
8387 this.Rows = source.Rows
8488 .ToSynchronizedCoupleView(r => this.vmTranslator.Translate(r, this))
8589 .ToSynchronizedSingleView()
90+ .WithINotifyCollectionChangedList()
8691 .AddTo(disposables);
8792
88- logger.Trace("BookmarkListViewModel.SynchronizeWith: collection view [{0}]", this.Rows.GetType().FullName);
89-
90- this.Source = source;
93+ logger.Trace("BookmarkDetailListViewModel.SynchronizeWith: source [{0}], collection view [{1}]",
94+ source.ToHashString(), this.Rows.GetType().FullName);
9195
92- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Rows)));
96+ this.Source = source;
97+ }
98+ else
99+ {
100+ logger.Trace("BookmarkDetailListViewModel.SynchronizeWith: viewmodel already synchronized to model [{0}]",
101+ this.Source.ToHashString());
102+ }
93103 }
94104
105+ #endregion
106+
107+ #region IDestructible, IDisposable
108+
95109 public void Destroy()
96110 {
97- this.disposables.Dispose();
111+ this.Dispose();
98112 }
99113
114+ protected virtual void Dispose(bool disposing)
115+ {
116+ if (!disposedValue)
117+ {
118+ if (disposing)
119+ {
120+ this.disposables.Dispose();
121+
122+ logger.Trace("BookmarkDetailListViewModel disposed.");
123+ }
124+
125+ disposedValue = true;
126+ }
127+ }
128+
129+ public void Dispose()
130+ {
131+ Dispose(disposing: true);
132+ GC.SuppressFinalize(this);
133+ }
134+
135+ #endregion
136+
100137 #region INavigationAware
101138
102139 public void OnNavigatedFrom(INavigationParameters parameters)
--- a/TestNarou2.Adaptor/Gateway/ViewModel/BookmarkViewModel.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/BookmarkViewModel.cs
@@ -1,23 +1,54 @@
1-using System.ComponentModel;
1+using NLog;
2+using System.ComponentModel;
23 using System.Reactive.Disposables;
34 using TestNarou2.Adaptor.Boundary.Gateway.ViewModel;
45
56 namespace TestNarou2.Adaptor.Gateway.ViewModel
67 {
7- internal class BookmarkViewModel : IBookmarkViewModel, IDestructible
8+ internal class BookmarkViewModel : IBookmarkViewModel, IDestructible, IDisposable
89 {
9- //private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
10+ private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
1011
1112 #pragma warning disable CS0067
1213 public event PropertyChangedEventHandler PropertyChanged;
1314 #pragma warning restore CS0067
1415
1516 private readonly CompositeDisposable disposables = new();
17+ private bool disposedValue;
18+
19+ #region IDestructible
1620
1721 public void Destroy()
1822 {
23+ this.Dispose();
24+ }
25+
26+ #endregion
27+
28+ #region IDisposable
29+
30+ protected virtual void Dispose(bool disposing)
31+ {
32+ if (!disposedValue)
33+ {
34+ if (disposing)
35+ {
1936 this.disposables.Dispose();
37+
38+ logger.Trace("BookmarkViewModel disposed.");
39+ }
40+
41+ disposedValue = true;
42+ }
43+ }
44+
45+ public void Dispose()
46+ {
47+ Dispose(disposing: true);
48+ GC.SuppressFinalize(this);
2049 }
2150
51+ #endregion
52+
2253 }
2354 }
--- a/TestNarou2.Adaptor/Gateway/ViewModel/Child/BookmarkCategoryRowViewModel.AfterMap.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/Child/BookmarkCategoryRowViewModel.AfterMap.cs
@@ -12,8 +12,6 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
1212 {
1313 d.Name.AddTo(d.disposables);
1414 d.Count.AddTo(d.disposables);
15- //d.IsSelected.AddTo(d.disposables);
16- //d.IsSelected.Subscribe(d.OnSelectedItemChanged).AddTo(d.disposables);
1715 }
1816 }
1917 }
--- a/TestNarou2.Adaptor/Gateway/ViewModel/Child/BookmarkCategoryRowViewModel.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/Child/BookmarkCategoryRowViewModel.cs
@@ -1,4 +1,5 @@
1-using Reactive.Bindings;
1+using NLog;
2+using Reactive.Bindings;
23 using System.Reactive.Disposables;
34 using TestNarou2.Adaptor.Boundary.Gateway.ViewModel;
45 using TestNarou2.Adaptor.Boundary.Gateway.ViewModel.Child;
@@ -12,11 +13,12 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
1213 ImageSource ItemImage,
1314 ReadOnlyReactiveProperty<string> Name,
1415 ReadOnlyReactiveProperty<int> Count,
15- //ReactiveProperty<bool> IsSelected,
1616 IBookmarkCategoryViewModel Parent,
1717 BookmarkCategoryRow Source
1818 ) : IBookmarkCategoryRowViewModel, IDisposable
1919 {
20+ private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
21+
2022 private readonly CompositeDisposable disposables = new();
2123 private bool disposedValue;
2224
@@ -26,23 +28,12 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
2628 ItemImage: ImageHelper.FolderImage,
2729 Name: null,
2830 Count: null,
29- //IsSelected: null,
3031 Parent: parent,
3132 Source: row
3233 )
3334 {
3435 }
35-#if false
36- private void OnSelectedItemChanged(bool isSelected)
37- {
38- if (!isSelected)
39- {
40- return;
41- }
4236
43- this.Parent.WindowController.NavigateBookmarkListView(this.Index);
44- }
45-#endif
4637 protected virtual void Dispose(bool disposing)
4738 {
4839 if (!disposedValue)
@@ -50,6 +41,7 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
5041 if (disposing)
5142 {
5243 this.disposables.Dispose();
44+ logger.Trace("BookmarkCategoryRowViewModel[{0}] disposed.", this.Index);
5345 }
5446
5547 disposedValue = true;
--- a/TestNarou2.Adaptor/Gateway/ViewModel/Child/BookmarkDetailListRowViewModel.AfterMap.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/Child/BookmarkDetailListRowViewModel.AfterMap.cs
@@ -28,9 +28,6 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
2828 d.AllPoint.AddTo(d.disposables);
2929 d.AllHyokaCnt.AddTo(d.disposables);
3030 d.NovelUpdatedAt.AddTo(d.disposables);
31-
32- //d.IsSelected.AddTo(d.disposables);
33- //d.IsSelected.Subscribe(d.OnSelectedItemChanged).AddTo(d.disposables);
3431 }
3532 }
3633 }
--- a/TestNarou2.Adaptor/Gateway/ViewModel/Child/BookmarkDetailListRowViewModel.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/Child/BookmarkDetailListRowViewModel.cs
@@ -1,4 +1,5 @@
1-using Reactive.Bindings;
1+using NLog;
2+using Reactive.Bindings;
23 using System.Reactive.Disposables;
34 using TestNarou2.Adaptor.Boundary.Gateway.ViewModel;
45 using TestNarou2.Adaptor.Boundary.Gateway.ViewModel.Child;
@@ -9,6 +10,8 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
910 internal partial record class BookmarkDetailListRowViewModel
1011 : IBookmarkDetailListRowViewModel, IDisposable
1112 {
13+ private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
14+
1215 public string NCode { get; private set; }
1316 public ReadOnlyReactiveProperty<string> Summary { get; private set; }
1417 public ReadOnlyReactiveProperty<string> Title { get; private set; }
@@ -32,7 +35,7 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
3235 public ReadOnlyReactiveProperty<string> GeneralFirstUp { get; private set; }
3336 public ReadOnlyReactiveProperty<string> GeneralLastUp { get; private set; }
3437 public ReadOnlyReactiveProperty<string> NovelUpdatedAt { get; private set; }
35- //public ReactiveProperty<bool> IsSelected { get; private set; }
38+
3639 public IBookmarkDetailListViewModel Parent { get; private set; }
3740 public BookmarkDetailListRow Source { get; private set; }
3841
@@ -46,18 +49,6 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
4649 this.Parent = parent;
4750 }
4851
49-#if false
50- private void OnSelectedItemChanged(bool isSelected)
51- {
52- if (!isSelected)
53- {
54- return;
55- }
56-
57- this.Parent.NotifySelectedItemChanged(this);
58- }
59-#endif
60-
6152 protected virtual void Dispose(bool disposing)
6253 {
6354 if (!disposedValue)
@@ -65,6 +56,7 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel.Child
6556 if (disposing)
6657 {
6758 this.disposables.Dispose();
59+ logger.Trace("BookmarkDetailListRowViewModel[{0}] disposed.", this.NCode);
6860 }
6961
7062 disposedValue = true;
--- a/TestNarou2.Adaptor/Gateway/ViewModel/LoginFormViewModel.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/LoginFormViewModel.cs
@@ -10,7 +10,7 @@ using TestNarou2.UseCase.Request;
1010
1111 namespace TestNarou2.Adaptor.Gateway.ViewModel
1212 {
13- internal class LoginFormViewModel : ILoginFormViewModel, IDestructible
13+ internal class LoginFormViewModel : ILoginFormViewModel, IDestructible, IDisposable
1414 {
1515 private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
1616
@@ -25,6 +25,7 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
2525 private readonly IAppWindowController wc;
2626
2727 private readonly CompositeDisposable disposables = new();
28+ private bool disposedValue;
2829
2930 public LoginFormViewModel(IAppWindowController wc)
3031 {
@@ -36,11 +37,37 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
3637 this.CommandLogin = new ReactiveCommand().WithSubscribe(OnLogin).AddTo(disposables);
3738 }
3839
40+ #region IDestructible, IDisposable
41+
3942 public void Destroy()
4043 {
44+ this.Dispose();
45+ }
46+
47+ protected virtual void Dispose(bool disposing)
48+ {
49+ if (!disposedValue)
50+ {
51+ if (disposing)
52+ {
4153 this.disposables.Dispose();
54+
55+ logger.Trace("LoginFormViewModel disposed.");
56+ }
57+
58+ disposedValue = true;
59+ }
60+ }
61+
62+ public void Dispose()
63+ {
64+ // このコードを変更しないでください。クリーンアップ コードを 'Dispose(bool disposing)' メソッドに記述します
65+ Dispose(disposing: true);
66+ GC.SuppressFinalize(this);
4267 }
4368
69+ #endregion
70+
4471 #region event handler
4572
4673 private async void OnLogin()
@@ -71,5 +98,6 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
7198 }
7299
73100 #endregion
101+
74102 }
75103 }
--- a/TestNarou2.Adaptor/Gateway/ViewModel/MainPageViewModel.cs
+++ /dev/null
@@ -1,52 +0,0 @@
1-using Reactive.Bindings;
2-using Reactive.Bindings.Extensions;
3-using System.Reactive.Disposables;
4-
5-namespace TestNarou2.Adaptor.Gateway.ViewModel
6-{
7- public class MainPageViewModel : IDisposable
8- {
9- public ReactiveProperty<string> Text { get; }
10-
11- public ReactiveCommand CommandClicked { get; }
12-
13- private int count = 0;
14-
15- private readonly CompositeDisposable disposables = new();
16- private bool disposedValue;
17-
18- public MainPageViewModel()
19- {
20- this.Text = new ReactiveProperty<string>("click me.").AddTo(disposables);
21-
22- this.CommandClicked = new ReactiveCommand().WithSubscribe(OnClicked).AddTo(disposables);
23- }
24-
25- private void OnClicked()
26- {
27- this.count++;
28- this.Text.Value = $"clicked {this.count} time(s).";
29-
30- SemanticScreenReader.Announce(this.Text.Value);
31- }
32-
33- protected virtual void Dispose(bool disposing)
34- {
35- if (!disposedValue)
36- {
37- if (disposing)
38- {
39- this.disposables.Dispose();
40- }
41-
42- disposedValue = true;
43- }
44- }
45-
46- public void Dispose()
47- {
48- Dispose(disposing: true);
49- GC.SuppressFinalize(this);
50- }
51- }
52-}
--- a/TestNarou2.Adaptor/Gateway/ViewModel/MainWindowViewModel.cs
+++ b/TestNarou2.Adaptor/Gateway/ViewModel/MainWindowViewModel.cs
@@ -1,4 +1,5 @@
1-using Reactive.Bindings;
1+using NLog;
2+using Reactive.Bindings;
23 using Reactive.Bindings.Extensions;
34 using System.Reactive.Disposables;
45 using TestNarou2.Adaptor.Boundary.Controller;
@@ -8,15 +9,18 @@ using TestNarou2.UseCase.Request;
89
910 namespace TestNarou2.Adaptor.Gateway.ViewModel
1011 {
11- internal class MainWindowViewModel : IMainWindowViewModel, IDestructible
12+ internal class MainWindowViewModel : IMainWindowViewModel, IDestructible, IDisposable
1213 {
13- private IAppWindowController wc;
14+ private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
1415
1516 public ReactiveProperty<string> Title { get; }
1617
1718 public ReactiveCommand CommandClosed { get; }
1819
20+ private readonly IAppWindowController wc;
21+
1922 private readonly CompositeDisposable disposables = new();
23+ private bool disposedValue;
2024
2125 public MainWindowViewModel(
2226 IAppCaptionFormatter caption,
@@ -33,12 +37,38 @@ namespace TestNarou2.Adaptor.Gateway.ViewModel
3337 {
3438 _ = this.wc.Execute(new NarouLogoutRequest());
3539 _ = this.wc.Execute(new AppConfigSaveRequest());
40+
41+ this.Dispose();
3642 }
3743
44+ #region IDestructible, IDisposable
45+
3846 public void Destroy()
3947 {
40- this.disposables.Dispose();
48+ this.Dispose();
49+ }
50+
51+ protected virtual void Dispose(bool disposing)
52+ {
53+ if (!disposedValue)
54+ {
55+ if (disposing)
56+ {
57+ this.disposables.Dispose();
58+
59+ logger.Trace("MainWindowViewModel disposed.");
60+ }
61+
62+ disposedValue = true;
63+ }
64+ }
65+
66+ public void Dispose()
67+ {
68+ Dispose(disposing: true);
69+ GC.SuppressFinalize(this);
4170 }
71+ #endregion
4272
4373 }
4474 }
--- a/TestNarou2.Adaptor/Translator/BookmarkCategoryRowViewModelTranslator.cs
+++ b/TestNarou2.Adaptor/Translator/BookmarkCategoryRowViewModelTranslator.cs
@@ -37,11 +37,6 @@ namespace TestNarou2.Adaptor.Translator
3737 opts => opts.MapFrom(s => s.Name))
3838 .ForMember(d => d.Count,
3939 opts => opts.MapFrom(s => s.Count))
40-#if false
41- .ForMember(d => d.IsSelected,
42- opts => opts.MapFrom(s => s.IsSelected
43- .ToReactivePropertyAsSynchronized(x => x.Value, ReactivePropertyMode.Default, false)))
44-#endif
4540 .ForMember(d => d.Parent,
4641 opts => opts.Ignore())
4742 .ForMember(d => d.Source,
--- a/TestNarou2.Adaptor/Translator/BookmarkDetailListRowViewModelTranslator.cs
+++ b/TestNarou2.Adaptor/Translator/BookmarkDetailListRowViewModelTranslator.cs
@@ -92,11 +92,6 @@ namespace TestNarou2.Adaptor.Translator
9292 opts => opts.ConvertUsing(new SubstringConverter(10), s => s.GeneralLastUp))
9393 .ForMember(d => d.NovelUpdatedAt,
9494 opts => opts.ConvertUsing(new SubstringConverter(10), s => s.NovelUpdatedAt))
95-#if false
96- .ForMember(d => d.IsSelected,
97- opts => opts.MapFrom(s => s.IsSelected
98- .ToReactivePropertyAsSynchronized(x => x.Value, ReactivePropertyMode.Default, false)))
99-#endif
10095 .ForMember(d => d.Parent,
10196 opts => opts.Ignore())
10297 .ForMember(d => d.Source,
--- a/TestNarou2.Domain/Boundary/Repository/INarouRepository.cs
+++ b/TestNarou2.Domain/Boundary/Repository/INarouRepository.cs
@@ -2,7 +2,7 @@
22
33 namespace TestNarou2.Domain.Boundary.Repository
44 {
5- public interface INarouRepository : IDestructible
5+ public interface INarouRepository : IDisposable
66 {
77 string Login(string id, string password);
88 void Logout(string dataToken);
--- a/TestNarou2.Domain/Model/Entity/BookmarkCategory.cs
+++ b/TestNarou2.Domain/Model/Entity/BookmarkCategory.cs
@@ -1,4 +1,5 @@
1-using ObservableCollections;
1+using NLog;
2+using ObservableCollections;
23 using TestNarou2.Domain.Model.Entity.Child;
34
45 namespace TestNarou2.Domain.Model.Entity
@@ -7,31 +8,20 @@ namespace TestNarou2.Domain.Model.Entity
78 ObservableList<BookmarkCategoryRow> Rows
89 ) : IDisposable
910 {
11+ private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
12+
1013 private bool disposedValue;
1114
1215 public BookmarkCategory() : this(
13- Rows: new ObservableList<BookmarkCategoryRow>()
14- )
15- {
16- }
17-
18- public BookmarkCategory(IEnumerable<BookmarkCategoryRow> lists) : this(
19- Rows: CreateRows(lists)
16+ Rows: new()
2017 )
2118 {
2219 }
2320
24- private static ObservableList<BookmarkCategoryRow>
25- CreateRows(IEnumerable<BookmarkCategoryRow> lists)
21+ public void Refresh(IEnumerable<BookmarkCategoryRow> rows)
2622 {
27- ObservableList<BookmarkCategoryRow> rows = new();
28-
29- foreach (var row in lists)
30- {
31- rows.Add(row);
32- }
33-
34- return rows;
23+ this.Rows.Clear();
24+ this.Rows.AddRange(rows);
3525 }
3626
3727 protected virtual void Dispose(bool disposing)
@@ -44,6 +34,8 @@ namespace TestNarou2.Domain.Model.Entity
4434 {
4535 row.Dispose();
4636 }
37+
38+ logger.Trace("BookmarkCategory disposed.");
4739 }
4840
4941 disposedValue = true;
--- a/TestNarou2.Domain/Model/Entity/BookmarkDetailList.cs
+++ b/TestNarou2.Domain/Model/Entity/BookmarkDetailList.cs
@@ -1,4 +1,5 @@
1-using ObservableCollections;
1+using NLog;
2+using ObservableCollections;
23 using TestNarou2.Domain.Model.Entity.Child;
34
45 namespace TestNarou2.Domain.Model.Entity
@@ -7,31 +8,20 @@ namespace TestNarou2.Domain.Model.Entity
78 ObservableList<BookmarkDetailListRow> Rows
89 ) : IDisposable
910 {
11+ private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
12+
1013 private bool disposedValue;
1114
1215 public BookmarkDetailList() : this(
13- Rows: new ObservableList<BookmarkDetailListRow>()
14- )
15- {
16- }
17-
18- public BookmarkDetailList(IEnumerable<BookmarkDetailListRow> lists) : this(
19- Rows: CreateRows(lists)
16+ Rows: new()
2017 )
2118 {
2219 }
2320
24- private static ObservableList<BookmarkDetailListRow>
25- CreateRows(IEnumerable<BookmarkDetailListRow> lists)
26- {
27- ObservableList<BookmarkDetailListRow> rows = new();
28-
29- foreach (var row in lists)
21+ public void Refresh(IEnumerable<BookmarkDetailListRow> rows)
3022 {
31- rows.Add(row);
32- }
33-
34- return rows;
23+ this.Rows.Clear();
24+ this.Rows.AddRange(rows);
3525 }
3626
3727 protected virtual void Dispose(bool disposing)
@@ -44,6 +34,8 @@ namespace TestNarou2.Domain.Model.Entity
4434 {
4535 row.Dispose();
4636 }
37+
38+ logger.Trace("BookmarkDetailList disposed.");
4739 }
4840
4941 disposedValue = true;
--- a/TestNarou2.Domain/Model/Entity/Child/BookmarkCategoryRow.cs
+++ b/TestNarou2.Domain/Model/Entity/Child/BookmarkCategoryRow.cs
@@ -1,4 +1,5 @@
1-using Reactive.Bindings;
1+using NLog;
2+using Reactive.Bindings;
23 using Reactive.Bindings.Extensions;
34 using System.Reactive.Disposables;
45
@@ -7,23 +8,22 @@ namespace TestNarou2.Domain.Model.Entity.Child
78 public partial record class BookmarkCategoryRow(
89 int Index,
910 ReactivePropertySlim<string> Name,
10- ReactivePropertySlim<int> Count,
11- ReactivePropertySlim<bool> IsSelected
11+ ReactivePropertySlim<int> Count
1212 ) : IDisposable
1313 {
14+ private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
15+
1416 private readonly CompositeDisposable disposables = new();
1517 private bool disposedValue;
1618
1719 public BookmarkCategoryRow(int index): this(
1820 Index: index,
1921 Name: new(),
20- Count: new(),
21- IsSelected: new()
22+ Count: new()
2223 )
2324 {
2425 this.Name.AddTo(this.disposables);
2526 this.Count.AddTo(this.disposables);
26- this.IsSelected.AddTo(this.disposables);
2727 }
2828
2929 protected virtual void Dispose(bool disposing)
@@ -33,6 +33,7 @@ namespace TestNarou2.Domain.Model.Entity.Child
3333 if (disposing)
3434 {
3535 this.disposables.Dispose();
36+ logger.Trace("BookmarkCategoryRow[{0}] disposed.", Index);
3637 }
3738
3839 disposedValue = true;
--- a/TestNarou2.Domain/Model/Entity/Child/BookmarkDetailListRow.cs
+++ b/TestNarou2.Domain/Model/Entity/Child/BookmarkDetailListRow.cs
@@ -1,4 +1,5 @@
1-using Reactive.Bindings;
1+using NLog;
2+using Reactive.Bindings;
23 using Reactive.Bindings.Extensions;
34 using System.Reactive.Disposables;
45
@@ -36,10 +37,11 @@ namespace TestNarou2.Domain.Model.Entity.Child
3637 ReactivePropertySlim<int> AllHyokaCnt,
3738 ReactivePropertySlim<string> GeneralFirstUp,
3839 ReactivePropertySlim<string> GeneralLastUp,
39- ReactivePropertySlim<string> NovelUpdatedAt,
40- ReactivePropertySlim<bool> IsSelected
40+ ReactivePropertySlim<string> NovelUpdatedAt
4141 ) : IDisposable
4242 {
43+ private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
44+
4345 private readonly CompositeDisposable disposables = new();
4446 private bool disposedValue;
4547
@@ -75,8 +77,7 @@ namespace TestNarou2.Domain.Model.Entity.Child
7577 AllHyokaCnt: new(),
7678 GeneralFirstUp: new(),
7779 GeneralLastUp: new(),
78- NovelUpdatedAt: new(),
79- IsSelected: new()
80+ NovelUpdatedAt: new()
8081 )
8182 {
8283 this.Title.AddTo(this.disposables);
@@ -109,7 +110,6 @@ namespace TestNarou2.Domain.Model.Entity.Child
109110 this.GeneralFirstUp.AddTo(this.disposables);
110111 this.GeneralLastUp.AddTo(this.disposables);
111112 this.NovelUpdatedAt.AddTo(this.disposables);
112- this.IsSelected.AddTo(this.disposables);
113113 }
114114
115115 protected virtual void Dispose(bool disposing)
@@ -119,6 +119,7 @@ namespace TestNarou2.Domain.Model.Entity.Child
119119 if (disposing)
120120 {
121121 this.disposables.Dispose();
122+ logger.Trace("BookmarkDetailListRow[{0}] disposed.", NCode);
122123 }
123124
124125 disposedValue = true;
--- a/TestNarou2.Domain/Service/NarouService.cs
+++ b/TestNarou2.Domain/Service/NarouService.cs
@@ -8,20 +8,22 @@ using TestNarou2.Domain.Translator;
88
99 namespace TestNarou2.Domain.Service
1010 {
11- internal class NarouService : INarouService, IDestructible
11+ internal class NarouService : INarouService, IDisposable
1212 {
1313 private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
1414
1515 private string DataToken { get; set; }
1616
17- private BookmarkCategory Categeory { get; set; }
18- private BookmarkDetailList DetailList { get; set; }
17+ private BookmarkCategory Categeory { get; }
18+ private BookmarkDetailList DetailList { get; }
1919
2020 private readonly INarouRepository repo;
2121
2222 private readonly IBookmarkCategoryRowTranslator vmCategoryRowTranslator;
2323 private readonly IBookmarkDetailListRowTranslator vmDetailRowTranslator;
2424
25+ private bool disposedValue;
26+
2527 public NarouService(
2628 INarouRepository repo,
2729 IBookmarkCategoryRowTranslator vmCategoryRowTranslator,
@@ -32,6 +34,9 @@ namespace TestNarou2.Domain.Service
3234
3335 this.vmCategoryRowTranslator = vmCategoryRowTranslator;
3436 this.vmDetailRowTranslator = vmDetailRowTranslator;
37+
38+ this.Categeory = new();
39+ this.DetailList = new();
3540 }
3641
3742 public void Login(string id, string password)
@@ -60,8 +65,7 @@ namespace TestNarou2.Domain.Service
6065 pair => this.vmCategoryRowTranslator.Translate(pair.category, pair.no)
6166 );
6267
63- this.Categeory?.Dispose();
64- this.Categeory = new(rows);
68+ this.Categeory.Refresh(rows);
6569
6670 return this.Categeory;
6771 }
@@ -75,18 +79,37 @@ namespace TestNarou2.Domain.Service
7579 IEnumerable<BookmarkDetailListRow> detailRows =
7680 novelInfos.Skip(1).Select(v => vmDetailRowTranslator.Translate(v));
7781
78- this.DetailList?.Dispose();
79- this.DetailList = new(detailRows);
82+ this.DetailList.Refresh(detailRows);
8083
8184 return this.DetailList;
8285 }
8386
84- public void Destroy()
87+ #region IDisposable
88+
89+ protected virtual void Dispose(bool disposing)
8590 {
86- this.Categeory?.Dispose();
87- this.DetailList?.Dispose();
91+ if (!disposedValue)
92+ {
93+ if (disposing)
94+ {
95+ this.Categeory?.Dispose();
96+ this.DetailList?.Dispose();
97+
98+ this.repo?.Dispose();
99+
100+ logger.Trace("NarouService disposed.");
101+ }
88102
89- this.repo?.Destroy();
103+ disposedValue = true;
104+ }
90105 }
106+
107+ public void Dispose()
108+ {
109+ Dispose(disposing: true);
110+ GC.SuppressFinalize(this);
111+ }
112+
113+ #endregion
91114 }
92115 }
--- a/TestNarou2.Domain/Translator/BookmarkCategoryRowTranslator.cs
+++ b/TestNarou2.Domain/Translator/BookmarkCategoryRowTranslator.cs
@@ -29,7 +29,6 @@ namespace TestNarou2.Domain.Translator
2929 .ForMember(d => d.Index, opts => opts.Ignore())
3030 .ForMember(d => d.Name, opts => opts.MapFrom(s => s.Name))
3131 .ForMember(d => d.Count, opts => opts.MapFrom(s => s.Count))
32- .ForMember(d => d.IsSelected, opts => opts.Ignore())
3332 .DisableCtorValidation();
3433 }
3534 }
--- a/TestNarou2.Domain/Translator/BookmarkDetailListRowTranslator.cs
+++ b/TestNarou2.Domain/Translator/BookmarkDetailListRowTranslator.cs
@@ -58,7 +58,6 @@ namespace TestNarou2.Domain.Translator
5858 .ForMember(d => d.GeneralFirstUp, opts => opts.MapFrom(s => s.GeneralFirstUp))
5959 .ForMember(d => d.GeneralLastUp, opts => opts.MapFrom(s => s.GeneralLastUp))
6060 .ForMember(d => d.NovelUpdatedAt, opts => opts.MapFrom(s => s.NovelUpdatedAt))
61- .ForMember(d => d.IsSelected, opts => opts.Ignore())
6261 .DisableCtorValidation();
6362 }
6463 }
--- a/TestNarou2.OuterEdge/Repository/API/HttpClientHelper.cs
+++ b/TestNarou2.OuterEdge/Repository/API/HttpClientHelper.cs
@@ -5,7 +5,7 @@ using System.Text;
55
66 namespace TestNarou2.OuterEdge.Repository.API
77 {
8- internal class HttpClientHelper : IDestructible
8+ internal class HttpClientHelper : IDisposable
99 {
1010 private static readonly ILogger logger = LogManager.GetCurrentClassLogger();
1111
@@ -20,6 +20,8 @@ namespace TestNarou2.OuterEdge.Repository.API
2020 private readonly HttpClientHandler httpClientHandler;
2121 private readonly HttpClient httpClient;
2222
23+ private bool disposedValue;
24+
2325 public HttpClientHelper()
2426 {
2527 cookies = new();
@@ -60,6 +62,30 @@ namespace TestNarou2.OuterEdge.Repository.API
6062 }
6163 }
6264
65+ #region IDisposable
66+
67+ protected virtual void Dispose(bool disposing)
68+ {
69+ if (!disposedValue)
70+ {
71+ if (disposing)
72+ {
73+ httpClient.Dispose();
74+ logger.Trace("HttpClientHelper disposed.");
75+ }
76+
77+ disposedValue = true;
78+ }
79+ }
80+
81+ public void Dispose()
82+ {
83+ Dispose(disposing: true);
84+ GC.SuppressFinalize(this);
85+ }
86+
87+ #endregion
88+
6389 public async Task<HttpResponseMessage> GetAsync(string url, string referer)
6490 {
6591 var request = CreateRequestMessage(url, referer, HttpMethod.Post);
@@ -169,10 +195,5 @@ namespace TestNarou2.OuterEdge.Repository.API
169195
170196 return Encoding.UTF8.GetString(raw);
171197 }
172-
173- public void Destroy()
174- {
175- httpClient.Dispose();
176- }
177198 }
178199 }
--- a/TestNarou2.OuterEdge/Repository/API/NarouRepository.cs
+++ b/TestNarou2.OuterEdge/Repository/API/NarouRepository.cs
@@ -45,6 +45,32 @@ namespace TestNarou2.OuterEdge.Repository.API
4545
4646 private readonly HttpClientHelper httpClient = new();
4747
48+ private bool disposedValue;
49+
50+ #region IDisposable
51+
52+ protected virtual void Dispose(bool disposing)
53+ {
54+ if (!disposedValue)
55+ {
56+ if (disposing)
57+ {
58+ this.httpClient?.Dispose();
59+ logger.Trace("NarouRepository disposed.");
60+ }
61+
62+ disposedValue = true;
63+ }
64+ }
65+
66+ public void Dispose()
67+ {
68+ Dispose(disposing: true);
69+ System.GC.SuppressFinalize(this);
70+ }
71+
72+ #endregion
73+
4874 public string Login(string id, string password)
4975 {
5076 var form = new Dictionary<string, string>()
@@ -252,11 +278,5 @@ namespace TestNarou2.OuterEdge.Repository.API
252278
253279 return json;
254280 }
255-
256- public void Destroy()
257- {
258- this.httpClient?.Destroy();
259- }
260-
261281 }
262282 }
--- a/TestNarou2.OuterEdge/UI/View/BookmarkCategoryView.xaml
+++ b/TestNarou2.OuterEdge/UI/View/BookmarkCategoryView.xaml
@@ -6,7 +6,7 @@
66 xmlns:vm="http://schemas.drillion.net/testnarou2/viewmodel">
77
88 <ListView ItemsSource="{Binding Rows}"
9- SelectedItem="{Binding SelectedItem.Value}" SelectionMode="Single">
9+ SelectedItem="{Binding SelectedItem.Value, Mode=TwoWay}" SelectionMode="Single">
1010
1111 <!--
1212 <ListView.Resources>
--- a/TestNarou2.sln
+++ b/TestNarou2.sln
@@ -26,6 +26,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CleanAuLait.Prism", "..\Cle
2626 EndProject
2727 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CleanAuLait.ObservableCollectionsMod", "..\CleanAuLait.ObservableCollectionsMod\CleanAuLait.ObservableCollectionsMod.csproj", "{6901733E-1944-48C0-8C61-2418ACE94AD3}"
2828 EndProject
29+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ObservableCollections", "D:\Repo\gitroot\ObservableCollectionsMod\src\ObservableCollections\ObservableCollections.csproj", "{6A4ED2F0-C62A-49FC-8189-5217A5E0EE6A}"
30+EndProject
2931 Global
3032 GlobalSection(SolutionConfigurationPlatforms) = preSolution
3133 Debug|Any CPU = Debug|Any CPU
@@ -74,6 +76,10 @@ Global
7476 {6901733E-1944-48C0-8C61-2418ACE94AD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
7577 {6901733E-1944-48C0-8C61-2418ACE94AD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
7678 {6901733E-1944-48C0-8C61-2418ACE94AD3}.Release|Any CPU.Build.0 = Release|Any CPU
79+ {6A4ED2F0-C62A-49FC-8189-5217A5E0EE6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
80+ {6A4ED2F0-C62A-49FC-8189-5217A5E0EE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
81+ {6A4ED2F0-C62A-49FC-8189-5217A5E0EE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
82+ {6A4ED2F0-C62A-49FC-8189-5217A5E0EE6A}.Release|Any CPU.Build.0 = Release|Any CPU
7783 EndGlobalSection
7884 GlobalSection(SolutionProperties) = preSolution
7985 HideSolutionNode = FALSE