diff --git a/csharp/Platform.Disposables.Tests/DisposableTests.cs b/csharp/Platform.Disposables.Tests/DisposableTests.cs index caa19fb..0f9e804 100644 --- a/csharp/Platform.Disposables.Tests/DisposableTests.cs +++ b/csharp/Platform.Disposables.Tests/DisposableTests.cs @@ -79,5 +79,108 @@ private static string GetDisposalObjectTestProjectFilePath() } return path; } + + [Fact] + public static void WrapSystemIDisposableInDisposableTest() + { + var disposed = false; + var testDisposable = new TestDisposable(() => disposed = true); + + // Test creating wrapper from System.IDisposable using Create method + var wrapper = Disposable.Create(testDisposable); + Assert.NotNull(wrapper); + Assert.False(disposed); + + wrapper.Dispose(); + Assert.True(disposed); + } + + [Fact] + public static void WrapSystemIDisposableInGenericDisposableTest() + { + var disposed = false; + var testDisposable = new TestDisposable(() => disposed = true); + + // Test creating generic wrapper from System.IDisposable using Create method + var wrapper = Disposable.Create(testDisposable); + Assert.NotNull(wrapper); + Assert.Same(testDisposable, wrapper.Object); + Assert.False(disposed); + + wrapper.Dispose(); + Assert.True(disposed); + } + + [Fact] + public static void WrapTwoSystemIDisposableInDisposableTest() + { + var disposed1 = false; + var disposed2 = false; + var testDisposable1 = new TestDisposable(() => disposed1 = true); + var testDisposable2 = new TestDisposable(() => disposed2 = true); + + // Test creating wrapper for two System.IDisposable objects using Create method + var wrapper = Disposable.Create((testDisposable1, testDisposable2)); + Assert.NotNull(wrapper); + Assert.Same(testDisposable1, wrapper.Object); + Assert.Same(testDisposable2, wrapper.AuxiliaryObject); + Assert.False(disposed1); + Assert.False(disposed2); + + wrapper.Dispose(); + Assert.True(disposed1); + Assert.True(disposed2); + } + + [Fact] + public static void AsDisposableExtensionMethodTest() + { + var disposed = false; + var testDisposable = new TestDisposable(() => disposed = true); + + // Test extension method that wraps System.IDisposable in Disposable + var wrapper = testDisposable.AsDisposable(); + Assert.NotNull(wrapper); + Assert.False(disposed); + + wrapper.Dispose(); + Assert.True(disposed); + } + + [Fact] + public static void AsDisposableContainerExtensionMethodTest() + { + var disposed = false; + var testDisposable = new TestDisposable(() => disposed = true); + + // Test extension method that wraps System.IDisposable in Disposable + var wrapper = testDisposable.AsDisposableContainer(); + Assert.NotNull(wrapper); + Assert.Same(testDisposable, wrapper.Object); + Assert.False(disposed); + + wrapper.Dispose(); + Assert.True(disposed); + } + + private class TestDisposable : System.IDisposable + { + private readonly Action _disposeAction; + private bool _disposed = false; + + public TestDisposable(Action disposeAction) + { + _disposeAction = disposeAction ?? throw new ArgumentNullException(nameof(disposeAction)); + } + + public void Dispose() + { + if (!_disposed) + { + _disposed = true; + _disposeAction(); + } + } + } } } diff --git a/csharp/Platform.Disposables/Disposable.cs b/csharp/Platform.Disposables/Disposable.cs index 9d0c028..0b77aa9 100644 --- a/csharp/Platform.Disposables/Disposable.cs +++ b/csharp/Platform.Disposables/Disposable.cs @@ -65,6 +65,14 @@ public Disposable(Action action) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Disposable(Disposal disposal) => new Disposable(disposal); + /// + /// Creates a new object that wraps the specified object. + /// Создает новый объект , который оборачивает указанный объект . + /// + /// The object to wrap.Объект для оборачивания. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Disposable Create(System.IDisposable disposable) => new Disposable(() => disposable?.Dispose()); + /// /// Disposes unmanaged resources. /// Высвобождает неуправляемые ресурсы. diff --git a/csharp/Platform.Disposables/Disposable[TPrimary, TAuxiliary].cs b/csharp/Platform.Disposables/Disposable[TPrimary, TAuxiliary].cs index 3fde638..5cd400b 100644 --- a/csharp/Platform.Disposables/Disposable[TPrimary, TAuxiliary].cs +++ b/csharp/Platform.Disposables/Disposable[TPrimary, TAuxiliary].cs @@ -111,6 +111,14 @@ public Disposable(TPrimary @object) : base(@object) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Disposable(ValueTuple tuple) => new Disposable(tuple.Item1, tuple.Item2); + /// + /// Creates a new object that wraps two objects and calls their Dispose methods when disposed. + /// Создает новый объект , который оборачивает два объекта и вызывает их методы Dispose при высвобождении. + /// + /// The tuple containing two objects to wrap.Кортеж, содержащий два объекта для оборачивания. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Disposable Create(ValueTuple disposables) => new Disposable(disposables.Item1, disposables.Item2, (obj1, obj2) => { obj1?.Dispose(); obj2?.Dispose(); }); + /// /// Creates a new copy of the primary object (). /// Создаёт новую копию основного объекта (). diff --git a/csharp/Platform.Disposables/Disposable[T].cs b/csharp/Platform.Disposables/Disposable[T].cs index e9f0790..2ce6863 100644 --- a/csharp/Platform.Disposables/Disposable[T].cs +++ b/csharp/Platform.Disposables/Disposable[T].cs @@ -96,6 +96,14 @@ public Disposable(T @object, Action action) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Disposable(T @object) => new Disposable(@object); + /// + /// Creates a new object that wraps the specified object and calls its Dispose method when disposed. + /// Создает новый объект , который оборачивает указанный объект и вызывает его метод Dispose при высвобождении. + /// + /// The object to wrap.Объект для оборачивания. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static new Disposable Create(System.IDisposable disposable) => new Disposable(disposable, obj => obj?.Dispose()); + /// /// Creates a new copy of the primary object (). /// Создаёт новую копию основного объекта (). diff --git a/csharp/Platform.Disposables/IDisposableExtensions.cs b/csharp/Platform.Disposables/IDisposableExtensions.cs index 3cff9b6..0a5afe7 100644 --- a/csharp/Platform.Disposables/IDisposableExtensions.cs +++ b/csharp/Platform.Disposables/IDisposableExtensions.cs @@ -21,5 +21,23 @@ public static void DisposeIfNotDisposed(this IDisposable disposable) disposable.Dispose(); } } + + /// + /// Wraps a object in a wrapper. + /// Оборачивает объект в обёртку . + /// + /// The object to wrap.Объект для оборачивания. + /// A new wrapper.Новая обёртка . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Disposable AsDisposable(this System.IDisposable disposable) => Disposable.Create(disposable); + + /// + /// Wraps a object in a wrapper. + /// Оборачивает объект в обёртку . + /// + /// The object to wrap.Объект для оборачивания. + /// A new wrapper.Новая обёртка . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Disposable AsDisposableContainer(this System.IDisposable disposable) => Disposable.Create(disposable); } }