From f6c96aa967b3717aee5349349ef05d210123ef09 Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Mon, 4 Apr 2022 10:37:23 +0900 Subject: [PATCH] =?utf8?q?DisposableLazy=20=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- OpenTween.Tests/DisposableLazyTest.cs | 85 +++++++++++++++++++++++++++++++++++ OpenTween/ApplicationContainer.cs | 17 ++++--- OpenTween/DisposableLazy.cs | 55 +++++++++++++++++++++++ OpenTween/OpenTween.csproj | 1 + 4 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 OpenTween.Tests/DisposableLazyTest.cs create mode 100644 OpenTween/DisposableLazy.cs diff --git a/OpenTween.Tests/DisposableLazyTest.cs b/OpenTween.Tests/DisposableLazyTest.cs new file mode 100644 index 00000000..15296f17 --- /dev/null +++ b/OpenTween.Tests/DisposableLazyTest.cs @@ -0,0 +1,85 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2022 kim_upsilon (@kim_upsilon) +// All rights reserved. +// +// This file is part of OpenTween. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License +// for more details. +// +// You should have received a copy of the GNU General public License along +// with this program. If not, see , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Moq; +using Xunit; + +namespace OpenTween +{ + public class DisposableLazyTest + { + [Fact] + public void Value_Test() + { + var mock = new Mock(); + var obj = mock.Object; + + var lazy = new DisposableLazy(() => obj); + Assert.False(lazy.IsValueCreated); + Assert.Equal(obj, lazy.Value); + Assert.True(lazy.IsValueCreated); + } + + [Fact] + public void Value_DisposedErrorTest() + { + var mock = new Mock(); + var obj = mock.Object; + + var lazy = new DisposableLazy(() => obj); + lazy.Dispose(); + + Assert.Throws(() => lazy.Value); + } + + [Fact] + public void Dispose_BeforeValueCreatedTest() + { + var mock = new Mock(); + + var lazy = new DisposableLazy(() => mock.Object); + lazy.Dispose(); + + Assert.False(lazy.IsValueCreated); + Assert.True(lazy.IsDisposed); + mock.Verify(x => x.Dispose(), Times.Never()); + } + + [Fact] + public void Dispose_AfterValueCreatedTest() + { + var mock = new Mock(); + + var lazy = new DisposableLazy(() => mock.Object); + _ = lazy.Value; + lazy.Dispose(); + + Assert.True(lazy.IsValueCreated); + Assert.True(lazy.IsDisposed); + mock.Verify(x => x.Dispose(), Times.Once()); + } + } +} diff --git a/OpenTween/ApplicationContainer.cs b/OpenTween/ApplicationContainer.cs index 1dfdc0fa..36eb8204 100644 --- a/OpenTween/ApplicationContainer.cs +++ b/OpenTween/ApplicationContainer.cs @@ -52,10 +52,10 @@ namespace OpenTween => this.mainFormLazy.Value; private readonly Lazy cultureServiceLazy; - private readonly Lazy twitterApiLazy; - private readonly Lazy twitterLazy; - private readonly Lazy imageCacheLazy; - private readonly Lazy mainFormLazy; + private readonly DisposableLazy twitterApiLazy; + private readonly DisposableLazy twitterLazy; + private readonly DisposableLazy imageCacheLazy; + private readonly DisposableLazy mainFormLazy; public ApplicationContainer() { @@ -87,11 +87,10 @@ namespace OpenTween return; this.IsDisposed = true; - this.MainForm.Dispose(); - this.Twitter.Dispose(); - this.TwitterApi.Dispose(); - this.ImageCache.CancelAsync(); - this.ImageCache.Dispose(); + this.mainFormLazy.Dispose(); + this.twitterLazy.Dispose(); + this.twitterApiLazy.Dispose(); + this.imageCacheLazy.Dispose(); } } } diff --git a/OpenTween/DisposableLazy.cs b/OpenTween/DisposableLazy.cs new file mode 100644 index 00000000..9687c12b --- /dev/null +++ b/OpenTween/DisposableLazy.cs @@ -0,0 +1,55 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2022 kim_upsilon (@kim_upsilon) +// All rights reserved. +// +// This file is part of OpenTween. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License +// for more details. +// +// You should have received a copy of the GNU General public License along +// with this program. If not, see , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +#nullable enable + +using System; + +namespace OpenTween +{ + public sealed class DisposableLazy : IDisposable + where T : IDisposable + { + public bool IsDisposed { get; private set; } = false; + + public T Value + => !this.IsDisposed ? this.lazy.Value : throw new ObjectDisposedException(nameof(this.lazy)); + + public bool IsValueCreated + => this.lazy.IsValueCreated; + + private readonly Lazy lazy; + + public DisposableLazy(Func factory) + => this.lazy = new(factory); + + public void Dispose() + { + if (this.IsDisposed) + return; + + if (this.IsValueCreated) + this.Value.Dispose(); + + this.IsDisposed = true; + } + } +} diff --git a/OpenTween/OpenTween.csproj b/OpenTween/OpenTween.csproj index d85932a0..7e879925 100644 --- a/OpenTween/OpenTween.csproj +++ b/OpenTween/OpenTween.csproj @@ -131,6 +131,7 @@ + -- 2.11.0