Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/Autofac/ContainerBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,21 @@ public IContainer Build(ContainerBuildOptions options = ContainerBuildOptions.No
var componentRegistry = ComponentRegistryBuilder.Build();

var result = new Container(componentRegistry);
if ((options & ContainerBuildOptions.IgnoreStartableComponents) == ContainerBuildOptions.None)
try
{
StartableManager.StartStartableComponents(Properties, result);
}
if ((options & ContainerBuildOptions.IgnoreStartableComponents) == ContainerBuildOptions.None)
{
StartableManager.StartStartableComponents(Properties, result);
}

// Run any build callbacks.
BuildCallbackManager.RunBuildCallbacks(result);
// Run any build callbacks.
BuildCallbackManager.RunBuildCallbacks(result);
}
catch
{
result.Dispose();
throw;
}

// Allow the reflection cache to empty any registration-time caches to save memory.
ReflectionCacheSet.Shared.OnContainerBuildClearCaches(_clearRegistrationCaches);
Expand Down
41 changes: 41 additions & 0 deletions test/Autofac.Specification.Test/Features/StartableTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,22 @@ public void Startable_WhenStartableCreatesChildScope_NoExceptionIsThrown()
Assert.NotNull(container);
}

[Fact]
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposal is part of the test.")]
public void Startable_WhenStartableThrows_DependenciesAreDisposed()
{
// Issue #1392 - disposable instances resolved to satisfy a startable should be
// disposed when the startable's Start() method throws.
var dependency = new DisposableDependency();
var builder = new ContainerBuilder();
builder.RegisterInstance(dependency);
builder.RegisterType<ThrowingStartable>().As<IStartable>().SingleInstance();

Assert.Throws<DependencyResolutionException>(() => builder.Build());

Assert.True(dependency.IsDisposed);
}

[Fact]
public void Startable_WhenStartIsSpecified_StartableComponentsAreStarted()
{
Expand Down Expand Up @@ -285,4 +301,29 @@ public void Start()
WasStarted = true;
}
}

private class DisposableDependency : IDisposable
{
public bool IsDisposed
{
get; private set;
}

public void Dispose()
{
IsDisposed = true;
}
}

private class ThrowingStartable : IStartable
{
public ThrowingStartable(DisposableDependency dependency)
{
}

public void Start()
{
throw new InvalidOperationException("Startable failed.");
}
}
}
Loading