diff --git a/src/SquidStd.Tui/Extensions/RegisterTuiExtensions.cs b/src/SquidStd.Tui/Extensions/RegisterTuiExtensions.cs index f7797450..d030e2e2 100644 --- a/src/SquidStd.Tui/Extensions/RegisterTuiExtensions.cs +++ b/src/SquidStd.Tui/Extensions/RegisterTuiExtensions.cs @@ -28,7 +28,10 @@ public IContainer RegisterView() where TView : class, ITuiView where TViewModel : TuiViewModel { - container.Register(Reuse.Transient); + // Views derive from Window (IDisposable). DryIoc refuses disposable transients by default; + // allow it without tracking — the view host disposes each view on Remove, so the container + // must not also dispose it (which would double-dispose). + container.Register(Reuse.Transient, setup: Setup.With(allowDisposableTransient: true)); container.Register(Reuse.Transient); container.Resolve().Map(typeof(TViewModel), typeof(TView)); diff --git a/tests/SquidStd.Tests/Tui/Extensions/RegisterTuiExtensionsTests.cs b/tests/SquidStd.Tests/Tui/Extensions/RegisterTuiExtensionsTests.cs index bc3e3cf5..8aefa735 100644 --- a/tests/SquidStd.Tests/Tui/Extensions/RegisterTuiExtensionsTests.cs +++ b/tests/SquidStd.Tests/Tui/Extensions/RegisterTuiExtensionsTests.cs @@ -24,6 +24,22 @@ public void Initialize() } } + // Real views derive from Window (IDisposable); this fake reproduces that shape. + private sealed class DisposableView : ITuiView, IDisposable + { + public void Bind(object viewModel) + { + } + + public void Initialize() + { + } + + public void Dispose() + { + } + } + [Fact] public void RegisterTui_RegistersNavigatorAndRegistry() { @@ -50,4 +66,16 @@ public void RegisterView_MapsAndResolvesBothTypes() Assert.NotNull(container.Resolve()); Assert.NotNull(container.Resolve()); } + + [Fact] + public void RegisterView_AllowsDisposableTransientView() + { + var container = new Container(); + container.RegisterTui(); + + // Real views are IDisposable (Window); DryIoc throws on disposable transients unless allowed. + container.RegisterView(); + + Assert.NotNull(container.Resolve()); + } }