From cbca5657889fb9a370f5b049d60dbae108104cfd Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Fri, 14 May 2021 03:00:57 +0300 Subject: [PATCH] ImageFrameCollection now properly implements IDisposable interface & ensures all operations are called on valid object --- src/ImageSharp/ImageFrameCollection.cs | 95 +++++++++++++++++-- .../ImageFrameCollection{TPixel}.cs | 3 +- 2 files changed, 88 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/ImageFrameCollection.cs b/src/ImageSharp/ImageFrameCollection.cs index 62ecc71f5..53ab2bf7c 100644 --- a/src/ImageSharp/ImageFrameCollection.cs +++ b/src/ImageSharp/ImageFrameCollection.cs @@ -11,8 +11,10 @@ namespace SixLabors.ImageSharp /// Encapsulates a pixel-agnostic collection of instances /// that make up an . /// - public abstract class ImageFrameCollection : IEnumerable + public abstract class ImageFrameCollection : IDisposable, IEnumerable { + private bool isDisposed; + /// /// Gets the number of frames. /// @@ -21,7 +23,15 @@ namespace SixLabors.ImageSharp /// /// Gets the root frame. /// - public ImageFrame RootFrame => this.NonGenericRootFrame; + public ImageFrame RootFrame + { + get + { + this.EnsureNotDisposed(); + + return this.NonGenericRootFrame; + } + } /// /// Gets the root frame. (Implements .) @@ -36,7 +46,15 @@ namespace SixLabors.ImageSharp /// /// The index. /// The at the specified index. - public ImageFrame this[int index] => this.NonGenericGetFrame(index); + public ImageFrame this[int index] + { + get + { + this.EnsureNotDisposed(); + + return this.NonGenericGetFrame(index); + } + } /// /// Determines the index of a specific in the . @@ -59,7 +77,12 @@ namespace SixLabors.ImageSharp /// /// The raw pixel data to generate the from. /// The cloned . - public ImageFrame AddFrame(ImageFrame source) => this.NonGenericAddFrame(source); + public ImageFrame AddFrame(ImageFrame source) + { + this.EnsureNotDisposed(); + + return this.NonGenericAddFrame(source); + } /// /// Removes the frame at the specified index and frees all freeable resources associated with it. @@ -91,7 +114,12 @@ namespace SixLabors.ImageSharp /// The zero-based index of the frame to export. /// Cannot remove last frame. /// The new with the specified frame. - public Image ExportFrame(int index) => this.NonGenericExportFrame(index); + public Image ExportFrame(int index) + { + this.EnsureNotDisposed(); + + return this.NonGenericExportFrame(index); + } /// /// Creates an with only the frame at the specified index @@ -99,7 +127,12 @@ namespace SixLabors.ImageSharp /// /// The zero-based index of the frame to clone. /// The new with the specified frame. - public Image CloneFrame(int index) => this.NonGenericCloneFrame(index); + public Image CloneFrame(int index) + { + this.EnsureNotDisposed(); + + return this.NonGenericCloneFrame(index); + } /// /// Creates a new and appends it to the end of the collection. @@ -107,7 +140,12 @@ namespace SixLabors.ImageSharp /// /// The new . /// - public ImageFrame CreateFrame() => this.NonGenericCreateFrame(); + public ImageFrame CreateFrame() + { + this.EnsureNotDisposed(); + + return this.NonGenericCreateFrame(); + } /// /// Creates a new and appends it to the end of the collection. @@ -116,14 +154,53 @@ namespace SixLabors.ImageSharp /// /// The new . /// - public ImageFrame CreateFrame(Color backgroundColor) => this.NonGenericCreateFrame(backgroundColor); + public ImageFrame CreateFrame(Color backgroundColor) + { + this.EnsureNotDisposed(); + + return this.NonGenericCreateFrame(backgroundColor); + } /// - public IEnumerator GetEnumerator() => this.NonGenericGetEnumerator(); + public void Dispose() + { + if (this.isDisposed) + { + return; + } + + this.DisposeManaged(); + + this.isDisposed = true; + } + + /// + public IEnumerator GetEnumerator() + { + this.EnsureNotDisposed(); + + return this.NonGenericGetEnumerator(); + } /// IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); + /// + /// Throws if the image frame is disposed. + /// + protected void EnsureNotDisposed() + { + if(this.isDisposed) + { + throw new ObjectDisposedException("Trying to execute an operation on a disposed image frame."); + } + } + + /// + /// Internal routine for freeing managed resources called from + /// + protected abstract void DisposeManaged(); + /// /// Implements . /// diff --git a/src/ImageSharp/ImageFrameCollection{TPixel}.cs b/src/ImageSharp/ImageFrameCollection{TPixel}.cs index 36c3ee481..b51e4dae5 100644 --- a/src/ImageSharp/ImageFrameCollection{TPixel}.cs +++ b/src/ImageSharp/ImageFrameCollection{TPixel}.cs @@ -335,7 +335,8 @@ namespace SixLabors.ImageSharp } } - internal void Dispose() + /// + protected override void DisposeManaged() { foreach (ImageFrame f in this.frames) {