Merge pull request #10968 from umbraco/v9/feature/composers-cleanup

Obsolete IUserComposer and rename Composers
This commit is contained in:
Bjarke Berg
2021-09-06 14:00:59 +02:00
committed by GitHub
6 changed files with 51 additions and 60 deletions

View File

@@ -9,28 +9,25 @@ using Umbraco.Cms.Core.DependencyInjection;
namespace Umbraco.Cms.Core.Composing
{
// note: this class is NOT thread-safe in any ways
// note: this class is NOT thread-safe in any way
/// <summary>
/// Handles the composers.
/// </summary>
public class Composers
internal class ComposerGraph
{
private readonly IUmbracoBuilder _builder;
private readonly ILogger<Composers> _logger;
private readonly ILogger<ComposerGraph> _logger;
private readonly IEnumerable<Type> _composerTypes;
private readonly IEnumerable<Attribute> _enableDisableAttributes;
private const int LogThresholdMilliseconds = 100;
/// <summary>
/// Initializes a new instance of the <see cref="Composers" /> class.
/// Initializes a new instance of the <see cref="ComposerGraph" /> class.
/// </summary>
/// <param name="builder">The composition.</param>
/// <param name="composerTypes">The <see cref="IComposer" /> types.</param>
/// <param name="enableDisableAttributes">The <see cref="EnableComposerAttribute" /> and/or <see cref="DisableComposerAttribute" /> attributes.</param>
/// <param name="logger">The logger.</param>
/// <param name="profileLogger">The profiling logger.</param>
/// <exception cref="ArgumentNullException">composition
/// or
/// composerTypes
@@ -38,7 +35,7 @@ namespace Umbraco.Cms.Core.Composing
/// enableDisableAttributes
/// or
/// logger</exception>
public Composers(IUmbracoBuilder builder, IEnumerable<Type> composerTypes, IEnumerable<Attribute> enableDisableAttributes, ILogger<Composers> logger)
public ComposerGraph(IUmbracoBuilder builder, IEnumerable<Type> composerTypes, IEnumerable<Attribute> enableDisableAttributes, ILogger<ComposerGraph> logger)
{
_builder = builder ?? throw new ArgumentNullException(nameof(builder));
_composerTypes = composerTypes ?? throw new ArgumentNullException(nameof(composerTypes));
@@ -48,8 +45,8 @@ namespace Umbraco.Cms.Core.Composing
private class EnableInfo
{
public bool Enabled;
public int Weight = -1;
public bool Enabled { get; set; }
public int Weight { get; set; } = -1;
}
/// <summary>
@@ -60,14 +57,9 @@ namespace Umbraco.Cms.Core.Composing
// make sure it is there
_builder.WithCollectionBuilder<ComponentCollectionBuilder>();
IEnumerable<Type> orderedComposerTypes;
IEnumerable<Type> orderedComposerTypes = PrepareComposerTypes();
orderedComposerTypes = PrepareComposerTypes();
var composers = InstantiateComposers(orderedComposerTypes);
foreach (var composer in composers)
foreach (IComposer composer in InstantiateComposers(orderedComposerTypes))
{
composer.Compose(_builder);
}
@@ -78,7 +70,7 @@ namespace Umbraco.Cms.Core.Composing
var requirements = GetRequirements();
// only for debugging, this is verbose
//_logger.Debug<Composers>(GetComposersReport(requirements));
//_logger.Debug<ComposerGraph>(GetComposersReport(requirements));
var sortedComposerTypes = SortComposers(requirements);
@@ -341,17 +333,19 @@ namespace Umbraco.Cms.Core.Composing
}
}
private IEnumerable<IComposer> InstantiateComposers(IEnumerable<Type> types)
private static IEnumerable<IComposer> InstantiateComposers(IEnumerable<Type> types)
{
IComposer InstantiateComposer(Type type)
foreach (Type type in types)
{
var ctor = type.GetConstructor(Array.Empty<Type>());
if (ctor == null)
throw new InvalidOperationException($"Composer {type.FullName} does not have a parameter-less constructor.");
return (IComposer)ctor.Invoke(Array.Empty<object>());
}
ConstructorInfo ctor = type.GetConstructor(Array.Empty<Type>());
return types.Select(InstantiateComposer).ToArray();
if (ctor == null)
{
throw new InvalidOperationException($"Composer {type.FullName} does not have a parameter-less constructor.");
}
yield return (IComposer) ctor.Invoke(Array.Empty<object>());
}
}
}
}

View File

@@ -1,11 +1,9 @@
namespace Umbraco.Cms.Core.Composing
namespace Umbraco.Cms.Core.Composing
{
/// <summary>
/// Represents a user <see cref="IComposer"/>.
/// </summary>
/// <remarks>
/// <para>User composers compose after core composers, and before the final composer.</para>
/// </remarks>
[System.Obsolete("This interface is obsolete. Use IComposer instead.")]
public interface IUserComposer : IComposer
{ }
}

View File

@@ -15,11 +15,10 @@ namespace Umbraco.Cms.Core.DependencyInjection
/// </summary>
public static IUmbracoBuilder AddComposers(this IUmbracoBuilder builder)
{
// TODO: Should have a better name
IEnumerable<Type> composerTypes = builder.TypeLoader.GetTypes<IComposer>();
IEnumerable<Attribute> enableDisable = builder.TypeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute));
new Composers(builder, composerTypes, enableDisable, builder.BuilderLoggerFactory.CreateLogger<Composers>()).Compose();
new ComposerGraph(builder, composerTypes, enableDisable, builder.BuilderLoggerFactory.CreateLogger<ComposerGraph>()).Compose();
return builder;
}

View File

@@ -6,7 +6,7 @@ using Umbraco.TestData.Extensions;
namespace Umbraco.TestData
{
public class LoadTestComposer : IUserComposer
public class LoadTestComposer : IComposer
{
public void Compose(IUmbracoBuilder builder) => builder.AddUmbracoTestData();
}

View File

@@ -46,7 +46,7 @@ namespace Umbraco.Cms.Tests.Integration
Assert.IsTrue(myComponent.IsTerminated, "The component was not terminated");
}
public class MyComposer : IUserComposer
public class MyComposer : IComposer
{
public void Compose(IUmbracoBuilder builder) => builder.Components().Append<MyComponent>();
}

View File

@@ -94,7 +94,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer1, Composer2, Composer4>();
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
// 2 is Core and requires 4
@@ -155,7 +155,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer1, Composer2, Composer3, Composer4>();
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
// 2 is Core and requires 4
@@ -172,7 +172,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer20, Composer21>();
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
// 21 is required by 20
@@ -188,7 +188,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer22, Composer24, Composer25>();
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
// i23 requires 22
@@ -206,7 +206,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer1, Composer2, Composer3>();
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
try
{
@@ -229,7 +229,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer2, Composer4, Composer13>();
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
// 2 is Core and requires 4
@@ -295,7 +295,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = new[] { typeof(Composer1), typeof(Composer5), typeof(Composer5a) };
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Assert.IsEmpty(Composed);
composers.Compose();
@@ -321,7 +321,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = new[] { typeof(Composer6), typeof(Composer7), typeof(Composer8) };
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
composers.Compose();
Assert.AreEqual(2, Composed.Count);
@@ -336,7 +336,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) };
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
composers.Compose();
Assert.AreEqual(3, Composed.Count);
@@ -353,7 +353,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) };
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
composers.Compose();
ComponentCollectionBuilder builder = composition.WithCollectionBuilder<ComponentCollectionBuilder>();
@@ -372,32 +372,32 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = new[] { typeof(Composer10) };
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
composers.Compose();
Assert.AreEqual(1, Composed.Count);
Assert.AreEqual(typeof(Composer10), Composed[0]);
types = new[] { typeof(Composer11) };
composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
Assert.Throws<Exception>(() => composers.Compose());
Console.WriteLine("throws:");
composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Dictionary<Type, List<Type>> requirements = composers.GetRequirements(false);
Console.WriteLine(Composers.GetComposersReport(requirements));
Console.WriteLine(ComposerGraph.GetComposersReport(requirements));
types = new[] { typeof(Composer2) };
composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
Assert.Throws<Exception>(() => composers.Compose());
Console.WriteLine("throws:");
composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
requirements = composers.GetRequirements(false);
Console.WriteLine(Composers.GetComposersReport(requirements));
Console.WriteLine(ComposerGraph.GetComposersReport(requirements));
types = new[] { typeof(Composer12) };
composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
composers.Compose();
Assert.AreEqual(1, Composed.Count);
@@ -411,7 +411,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = new[] { typeof(Composer6), typeof(Composer8) }; // 8 disables 7 which is not in the list
var composers = new Composers(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
composers.Compose();
Assert.AreEqual(2, Composed.Count);
@@ -427,13 +427,13 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
Type[] types = new[] { typeof(Composer26) };
DisableComposerAttribute[] enableDisableAttributes = new[] { new DisableComposerAttribute(typeof(Composer26)) };
var composers = new Composers(composition, types, enableDisableAttributes, Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(composition, types, enableDisableAttributes, Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
composers.Compose();
Assert.AreEqual(0, Composed.Count); // 26 gone
types = new[] { typeof(Composer26), typeof(Composer27) }; // 26 disabled by assembly attribute, enabled by 27
composers = new Composers(composition, types, enableDisableAttributes, Mock.Of<ILogger<Composers>>());
composers = new ComposerGraph(composition, types, enableDisableAttributes, Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
composers.Compose();
Assert.AreEqual(2, Composed.Count); // both
@@ -452,9 +452,9 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
var allComposers = typeLoader.GetTypes<IComposer>().ToList();
var types = allComposers.Where(x => x.FullName.StartsWith("Umbraco.Core.") || x.FullName.StartsWith("Umbraco.Web")).ToList();
var composers = new Composers(builder, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<Composers>>());
var composers = new ComposerGraph(builder, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Dictionary<Type, List<Type>> requirements = composers.GetRequirements();
string report = Composers.GetComposersReport(requirements);
string report = ComposerGraph.GetComposersReport(requirements);
Console.WriteLine(report);
IEnumerable<Type> composerTypes = composers.SortComposers(requirements);
@@ -478,7 +478,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
{
}
public class Composer3 : TestComposerBase, IUserComposer
public class Composer3 : TestComposerBase, IComposer
{
}
@@ -539,7 +539,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
{
}
public interface ITestComposer : IUserComposer
public interface ITestComposer : IComposer
{
}