@@ -9,6 +9,7 @@ namespace AutofacContrib.NSubstitute
99{
1010 public class AutoSubstituteBuilder
1111 {
12+ private readonly Dictionary < Type , object > _customDataManager ;
1213 private readonly Dictionary < Type , object > _substituteForRegistrations ;
1314 private readonly List < Action < IComponentContext > > _afterBuildActions ;
1415 private readonly ContainerBuilder _builder ;
@@ -20,18 +21,20 @@ public class AutoSubstituteBuilder
2021 public AutoSubstituteBuilder ( )
2122 {
2223 _substituteForRegistrations = new Dictionary < Type , object > ( ) ;
24+ _customDataManager = new Dictionary < Type , object > ( ) ;
2325 _afterBuildActions = new List < Action < IComponentContext > > ( ) ;
2426 _builder = new ContainerBuilder ( ) ;
2527 _options = new AutoSubstituteOptions ( ) ;
2628 }
27-
29+
2830 /// <summary>
2931 /// Creates a new instance that allows linking to the previous instance for derived builders.
3032 /// </summary>
3133 /// <param name="other">A <see cref="AutoSubstituteBuilder"/> that should be connected to this instance</param>
32- private protected AutoSubstituteBuilder ( AutoSubstituteBuilder other )
34+ protected AutoSubstituteBuilder ( AutoSubstituteBuilder other )
3335 {
3436 _substituteForRegistrations = other . _substituteForRegistrations ;
37+ _customDataManager = other . _customDataManager ;
3538 _afterBuildActions = other . _afterBuildActions ;
3639 _builder = other . _builder ;
3740 _options = other . _options ;
@@ -277,15 +280,53 @@ private SubstituteForBuilder<TService> CreateSubstituteForBuilder<TService>(Func
277280 return builder ;
278281 }
279282
280- private protected IProvidedValue < TService > CreateProvidedValue < TService > ( Func < IComponentContext , TService > factory )
283+ /// <summary>
284+ /// Registers a callback for about <see cref="Build"/> is called.
285+ /// </summary>
286+ /// <param name="callback">Callback to call.</param>
287+ protected void RegisterBuildCallback ( Action < IComponentContext > callback )
288+ => _afterBuildActions . Add ( callback ) ;
289+
290+ /// <summary>
291+ /// Creates a delayed provided value with the given factory method.
292+ /// </summary>
293+ /// <typeparam name="TService">Service to expose for the provided value.</typeparam>
294+ /// <param name="factory">Factory to create value.</param>
295+ /// <returns>A provided value.</returns>
296+ protected IProvidedValue < TService > CreateProvidedValue < TService > ( Func < IComponentContext , TService > factory )
281297 {
282298 var value = new ProvidedValue < TService > ( factory ) ;
283299
284- _afterBuildActions . Add ( c => value . SetComponentContext ( c ) ) ;
300+ RegisterBuildCallback ( c => value . SetComponentContext ( c ) ) ;
285301
286302 return value ;
287303 }
288304
305+ /// <summary>
306+ /// Retrieves storage of item that needs to be persisted across multiple calls to configuration methods.
307+ /// Some methods will wrap the builder into a new object, so this ensures that data used in one builder
308+ /// can be accessed later on.
309+ ///
310+ /// Since the data is keyed by type, it is recommended to use a custom data type to hold the data if it
311+ /// is a well-known type.
312+ /// </summary>
313+ /// <typeparam name="T">Type of custom data.</typeparam>
314+ /// <param name="factory">Factory to create data.</param>
315+ /// <returns>A cached instance of the data, or a new instance if not already available.</returns>
316+ protected T GetCustomData < T > ( Func < T > factory )
317+ {
318+ if ( _customDataManager . TryGetValue ( typeof ( T ) , out var result ) )
319+ {
320+ return ( T ) result ;
321+ }
322+
323+ var created = factory ( ) ;
324+
325+ _customDataManager . Add ( typeof ( T ) , created ) ;
326+
327+ return created ;
328+ }
329+
289330 private class ProvidedValue < T > : IProvidedValue < T >
290331 {
291332 private readonly Func < IComponentContext , T > _factory ;
0 commit comments