OSDN Git Service

DisposableLazy<T> を追加
authorKimura Youichi <kim.upsilon@bucyou.net>
Mon, 4 Apr 2022 01:37:23 +0000 (10:37 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Fri, 15 Apr 2022 20:04:50 +0000 (05:04 +0900)
OpenTween.Tests/DisposableLazyTest.cs [new file with mode: 0644]
OpenTween/ApplicationContainer.cs
OpenTween/DisposableLazy.cs [new file with mode: 0644]
OpenTween/OpenTween.csproj

diff --git a/OpenTween.Tests/DisposableLazyTest.cs b/OpenTween.Tests/DisposableLazyTest.cs
new file mode 100644 (file)
index 0000000..15296f1
--- /dev/null
@@ -0,0 +1,85 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2022 kim_upsilon (@kim_upsilon) <https://upsilo.net/~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 <http://www.gnu.org/licenses/>, 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<IDisposable>();
+            var obj = mock.Object;
+
+            var lazy = new DisposableLazy<IDisposable>(() => obj);
+            Assert.False(lazy.IsValueCreated);
+            Assert.Equal(obj, lazy.Value);
+            Assert.True(lazy.IsValueCreated);
+        }
+
+        [Fact]
+        public void Value_DisposedErrorTest()
+        {
+            var mock = new Mock<IDisposable>();
+            var obj = mock.Object;
+
+            var lazy = new DisposableLazy<IDisposable>(() => obj);
+            lazy.Dispose();
+
+            Assert.Throws<ObjectDisposedException>(() => lazy.Value);
+        }
+
+        [Fact]
+        public void Dispose_BeforeValueCreatedTest()
+        {
+            var mock = new Mock<IDisposable>();
+
+            var lazy = new DisposableLazy<IDisposable>(() => 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<IDisposable>();
+
+            var lazy = new DisposableLazy<IDisposable>(() => mock.Object);
+            _ = lazy.Value;
+            lazy.Dispose();
+
+            Assert.True(lazy.IsValueCreated);
+            Assert.True(lazy.IsDisposed);
+            mock.Verify(x => x.Dispose(), Times.Once());
+        }
+    }
+}
index 1dfdc0f..36eb820 100644 (file)
@@ -52,10 +52,10 @@ namespace OpenTween
             => this.mainFormLazy.Value;
 
         private readonly Lazy<CultureService> cultureServiceLazy;
-        private readonly Lazy<TwitterApi> twitterApiLazy;
-        private readonly Lazy<Twitter> twitterLazy;
-        private readonly Lazy<ImageCache> imageCacheLazy;
-        private readonly Lazy<TweenMain> mainFormLazy;
+        private readonly DisposableLazy<TwitterApi> twitterApiLazy;
+        private readonly DisposableLazy<Twitter> twitterLazy;
+        private readonly DisposableLazy<ImageCache> imageCacheLazy;
+        private readonly DisposableLazy<TweenMain> 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 (file)
index 0000000..9687c12
--- /dev/null
@@ -0,0 +1,55 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2022 kim_upsilon (@kim_upsilon) <https://upsilo.net/~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 <http://www.gnu.org/licenses/>, 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<T> : 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<T> lazy;
+
+        public DisposableLazy(Func<T> factory)
+            => this.lazy = new(factory);
+
+        public void Dispose()
+        {
+            if (this.IsDisposed)
+                return;
+
+            if (this.IsValueCreated)
+                this.Value.Dispose();
+
+            this.IsDisposed = true;
+        }
+    }
+}
index d85932a..7e87992 100644 (file)
     <Compile Include="Connection\IApiConnection.cs" />
     <Compile Include="CultureService.cs" />
     <Compile Include="DebounceTimer.cs" />
+    <Compile Include="DisposableLazy.cs" />
     <Compile Include="ErrorReportHandler.cs" />
     <Compile Include="IsExternalInit.cs" />
     <Compile Include="MediaUploadServices\IMediaUploadService.cs" />