Refactor collection builders to be nicer with DI

This commit is contained in:
Stephan
2019-01-04 08:53:51 +01:00
parent 3f1843def0
commit f6cd13488e
8 changed files with 43 additions and 45 deletions

View File

@@ -89,7 +89,10 @@ namespace Umbraco.Core.Components
onCreating();
foreach (var unique in _uniques.Values)
unique.RegisterTo(_register);
unique.RegisterWith(_register);
foreach (var builder in _builders.Values)
builder.RegisterWith(_register);
return _register.CreateFactory();
}
@@ -147,7 +150,7 @@ namespace Umbraco.Core.Components
_instance = instance;
}
public virtual void RegisterTo(IRegister register)
public virtual void RegisterWith(IRegister register)
{
if (_implementingType != null)
register.Register(_serviceType, _implementingType, Lifetime.Singleton);
@@ -166,7 +169,7 @@ namespace Umbraco.Core.Components
_factory = factory;
}
public override void RegisterTo(IRegister register)
public override void RegisterWith(IRegister register)
{
register.Register(_factory, Lifetime.Singleton);
}
@@ -190,10 +193,7 @@ namespace Umbraco.Core.Components
return (TBuilder) o;
var builder = new TBuilder();
builder.Initialize(_register);
_builders[typeOfBuilder] = builder;
return builder;
}

View File

@@ -18,29 +18,22 @@ namespace Umbraco.Core.Composing
private readonly object _locker = new object();
private Type[] _registeredTypes;
/// <summary>
/// Gets the container.
/// </summary>
protected IRegister Container { get; private set; }
/// <summary>
/// Gets the internal list of types as an IEnumerable (immutable).
/// </summary>
public IEnumerable<Type> GetTypes() => _types;
/// <summary>
/// Initializes a new instance of the builder.
/// </summary>
/// <remarks>By default, this registers the collection automatically.</remarks>
public virtual void Initialize(IRegister container)
/// <inheritdoc />
public virtual void RegisterWith(IRegister register)
{
if (Container != null)
throw new InvalidOperationException("This builder has already been initialized.");
Container = container;
if (_registeredTypes != null)
throw new InvalidOperationException("This builder has already been registered.");
// register the collection
Container.Register(CreateCollection, CollectionLifetime);
register.Register(CreateCollection, CollectionLifetime);
// register the types
RegisterTypes(register);
}
/// <summary>
@@ -58,7 +51,7 @@ namespace Umbraco.Core.Composing
lock (_locker)
{
if (_registeredTypes != null)
throw new InvalidOperationException("Cannot configure a collection builder after its types have been resolved.");
throw new InvalidOperationException("Cannot configure a collection builder after it has been registered.");
action(_types);
}
}
@@ -74,7 +67,7 @@ namespace Umbraco.Core.Composing
return types;
}
private void RegisterTypes()
private void RegisterTypes(IRegister register)
{
lock (_locker)
{
@@ -88,7 +81,7 @@ namespace Umbraco.Core.Composing
// register them
foreach (var type in types)
Container.Register(type);
register.Register(type);
_registeredTypes = types;
}
@@ -100,7 +93,8 @@ namespace Umbraco.Core.Composing
/// <returns>The collection items.</returns>
protected virtual IEnumerable<TItem> CreateItems(IFactory factory)
{
RegisterTypes(); // will do it only once
if (_registeredTypes == null)
throw new InvalidOperationException("Cannot create items before the collection builder has been registered.");
return _registeredTypes // respect order
.Select(x => CreateItem(factory, x))

View File

@@ -6,9 +6,10 @@
public interface ICollectionBuilder
{
/// <summary>
/// Initializes a new instance of the builder, and registers the collection.
/// Registers the builder so it can build the collection, by
/// registering the collection and the types.
/// </summary>
void Initialize(IRegister container);
void RegisterWith(IRegister register);
}
/// <summary>

View File

@@ -6,9 +6,9 @@ namespace Umbraco.Core.Persistence.Mappers
{
protected override MapperCollectionBuilder This => this;
public override void Initialize(IRegister container)
public override void RegisterWith(IRegister register)
{
base.Initialize(container);
base.RegisterWith(register);
// default initializer registers
// - service MapperCollectionBuilder, returns MapperCollectionBuilder
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Persistence.Mappers
// we want to register extra
// - service IMapperCollection, returns MappersCollectionBuilder's collection
Container.Register<IMapperCollection>(factory => factory.GetInstance<MapperCollection>());
register.Register<IMapperCollection>(factory => factory.GetInstance<MapperCollection>());
}
public MapperCollectionBuilder AddCoreMappers()

View File

@@ -184,7 +184,9 @@ namespace Umbraco.Tests.Components
Composed.Clear();
Initialized.Clear();
composers.Compose();
var components = composition.WithCollectionBuilder<ComponentCollectionBuilder>().CreateCollection(factory);
var builder = composition.WithCollectionBuilder<ComponentCollectionBuilder>();
builder.RegisterWith(register);
var components = builder.CreateCollection(factory);
Assert.AreEqual(2, Composed.Count);
Assert.AreEqual(typeof(Composer1), Composed[0]);
Assert.AreEqual(typeof(Composer5), Composed[1]);
@@ -234,7 +236,9 @@ namespace Umbraco.Tests.Components
var composers = new Composers(composition, types, Mock.Of<IProfilingLogger>());
Composed.Clear();
composers.Compose();
var components = composition.WithCollectionBuilder<ComponentCollectionBuilder>().CreateCollection(factory);
var builder = composition.WithCollectionBuilder<ComponentCollectionBuilder>();
builder.RegisterWith(register);
var components = builder.CreateCollection(factory);
Assert.AreEqual(3, Composed.Count);
Assert.AreEqual(typeof(Composer4), Composed[0]);
Assert.AreEqual(typeof(Composer2), Composed[1]);

View File

@@ -129,12 +129,10 @@ namespace Umbraco.Tests.Composing
// legal so far...
.Add(() => new[] { typeof(TransientObject4) });
var factory = composition.CreateFactory();
Assert.Throws<InvalidOperationException>(() =>
{
// but throws here when trying to register the types
var values = factory.GetInstance<TestCollection>();
// but throws here when trying to register the types, right before creating the factory
var factory = composition.CreateFactory();
});
}

View File

@@ -37,20 +37,21 @@ namespace Umbraco.Tests.TestHelpers
var container = RegisterFactory.Create();
var composition = new Composition(container, new TypeLoader(), Mock.Of<IProfilingLogger>(), ComponentTests.MockRuntimeState(RuntimeLevel.Run));
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
var typeLoader = new TypeLoader(NullCacheProvider.Instance,
LocalTempStorage.Default,
logger,
false);
var composition = new Composition(container, typeLoader, Mock.Of<IProfilingLogger>(), ComponentTests.MockRuntimeState(RuntimeLevel.Run));
composition.RegisterUnique<ILogger>(_ => Mock.Of<ILogger>());
composition.RegisterUnique<IProfiler>(_ => Mock.Of<IProfiler>());
var logger = new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>());
var pluginManager = new TypeLoader(NullCacheProvider.Instance,
LocalTempStorage.Default,
logger,
false);
composition.RegisterUnique(pluginManager);
composition.RegisterUnique(typeLoader);
composition.WithCollectionBuilder<MapperCollectionBuilder>()
.Add(() => Current.TypeLoader.GetAssignedMapperTypes());
.Add(() => composition.TypeLoader.GetAssignedMapperTypes());
var factory = Current.Factory = composition.CreateFactory();

View File

@@ -32,7 +32,7 @@ using Current = Umbraco.Web.Composing.Current;
namespace Umbraco.Web.Runtime
{
internal sealed class WebRuntimeComponent : IComponent
public sealed class WebRuntimeComponent : IComponent
{
public WebRuntimeComponent(
IRuntimeState runtime,