Skip to content

Commit 7fa6c29

Browse files
authored
Merge pull request #40 from twsouthwick/container-builder
Add container configuration method
2 parents 1dc9ad9 + e6b5954 commit 7fa6c29

File tree

3 files changed

+44
-21
lines changed

3 files changed

+44
-21
lines changed

AutofacContrib.NSubstitute.Tests/ExampleFixture.cs

+15
Original file line numberDiff line numberDiff line change
@@ -219,5 +219,20 @@ public void Example_provide_service_with_out_param()
219219

220220
Assert.AreSame(result, c.Value);
221221
}
222+
223+
[Test]
224+
public void CustomContainerBuilder()
225+
{
226+
var container = Substitute.For<IContainer>();
227+
228+
using var mock = AutoSubstitute.Configure()
229+
.ConfigureOptions(options =>
230+
{
231+
options.BuildContainerFactory = _ => container;
232+
})
233+
.Build();
234+
235+
Assert.AreSame(container, mock.Container);
236+
}
222237
}
223238
}

AutofacContrib.NSubstitute/AutoSubstituteBuilder.cs

+20-20
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,23 @@ namespace AutofacContrib.NSubstitute
99
{
1010
public class AutoSubstituteBuilder
1111
{
12-
private readonly Dictionary<Type, object> _substituteForRegistrations = new Dictionary<Type, object>();
13-
private readonly List<IProvidedValue> _providedValues;
12+
private readonly Dictionary<Type, object> _substituteForRegistrations;
13+
private readonly List<Action<IComponentContext>> _afterBuildActions;
1414
private readonly ContainerBuilder _builder;
1515
private readonly AutoSubstituteOptions _options;
1616

1717
public AutoSubstituteBuilder()
1818
{
19+
_substituteForRegistrations = new Dictionary<Type, object>();
20+
_afterBuildActions = new List<Action<IComponentContext>>();
1921
_builder = new ContainerBuilder();
20-
_providedValues = new List<IProvidedValue>();
2122
_options = new AutoSubstituteOptions();
2223
}
2324

25+
/// <summary>
26+
/// Builds an <see cref="AutoSubstitute"/> from the current builder.
27+
/// </summary>
28+
/// <returns>A new <see cref="AutoSubstitute"/> instance.</returns>
2429
public AutoSubstitute Build()
2530
=> new AutoSubstitute(InternalBuild());
2631

@@ -38,11 +43,11 @@ internal IContainer InternalBuild()
3843
});
3944
_builder.RegisterSource(new NSubstituteRegistrationHandler(_options));
4045

41-
var container = _builder.Build();
46+
var container = _options.BuildContainerFactory(_builder);
4247

43-
foreach (var provided in _providedValues)
48+
foreach (var action in _afterBuildActions)
4449
{
45-
provided.SetContainer(container);
50+
action(container);
4651
}
4752

4853
return container;
@@ -269,27 +274,22 @@ private SubstituteForBuilder<TService> CreateSubstituteForBuilder<TService>(Func
269274
return builder;
270275
}
271276

272-
internal IProvidedValue<TService> CreateProvidedValue<TService>(Func<IContainer, TService> factory)
277+
internal IProvidedValue<TService> CreateProvidedValue<TService>(Func<IComponentContext, TService> factory)
273278
{
274279
var value = new ProvidedValue<TService>(factory);
275280

276-
_providedValues.Add(value);
281+
_afterBuildActions.Add(c => value.SetComponentContext(c));
277282

278283
return value;
279284
}
280285

281-
private interface IProvidedValue
282-
{
283-
void SetContainer(IContainer container);
284-
}
285-
286-
private class ProvidedValue<T> : IProvidedValue<T>, IProvidedValue
286+
private class ProvidedValue<T> : IProvidedValue<T>
287287
{
288-
private readonly Func<IContainer, T> _factory;
288+
private readonly Func<IComponentContext, T> _factory;
289289

290-
private IContainer _container;
290+
private IComponentContext _componentContext;
291291

292-
public ProvidedValue(Func<IContainer, T> factory)
292+
public ProvidedValue(Func<IComponentContext, T> factory)
293293
{
294294
_factory = factory;
295295
}
@@ -298,16 +298,16 @@ public T Value
298298
{
299299
get
300300
{
301-
if (_container is null)
301+
if (_componentContext is null)
302302
{
303303
throw new InvalidOperationException("Build must be called before using a provided value.");
304304
}
305305

306-
return _factory(_container);
306+
return _factory(_componentContext);
307307
}
308308
}
309309

310-
public void SetContainer(IContainer container) => _container = container;
310+
public void SetComponentContext(IComponentContext c) => _componentContext = c;
311311
}
312312
}
313313
}

AutofacContrib.NSubstitute/AutoSubstituteOptions.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
using Autofac.Builder;
1+
using Autofac;
2+
using Autofac.Builder;
23
using System;
34
using System.Collections.Generic;
45

56
namespace AutofacContrib.NSubstitute
67
{
78
public class AutoSubstituteOptions
89
{
10+
private readonly static Func<ContainerBuilder, IContainer> _defaultContainerBuilder = b => b.Build();
11+
912
internal bool AutoInjectProperties { get; set; }
1013

1114
/// <summary>
@@ -27,5 +30,10 @@ public class AutoSubstituteOptions
2730
/// Gets or sets a flag indicating whether mocks should be excluded for provided values. This will automatically add values given to Provide methods to <see cref="TypesToSkipForMocking"/>.
2831
/// </summary>
2932
public bool AutomaticallySkipMocksForProvidedValues { get; set; }
33+
34+
/// <summary>
35+
/// Gets or sets a factory to create an <see cref="IContainer"/> given a <see cref="ContainerBuilder"/>. This defaults to simply calling <see cref="ContainerBuilder.Build()"/>.
36+
/// </summary>
37+
public Func<ContainerBuilder, IContainer> BuildContainerFactory { get; set; } = _defaultContainerBuilder;
3038
}
3139
}

0 commit comments

Comments
 (0)