Cleanup registrations

This commit is contained in:
Stephan
2018-07-23 08:56:08 +02:00
parent a00f2f0bb9
commit d2376bf4e3
19 changed files with 102 additions and 84 deletions

View File

@@ -313,7 +313,7 @@ namespace Umbraco.Core.Components
{
var componentType = component.GetType();
var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(x => x.Name == "Initialize" && x.IsGenericMethod == false);
.Where(x => x.Name == "Initialize" && x.IsGenericMethod == false && x.IsStatic == false);
using (_proflog.DebugDuration<BootLoader>($"Initializing {componentType.FullName}.", $"Initialised {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds))
{
foreach (var initializer in initializers)

View File

@@ -1,4 +1,5 @@
using Umbraco.Core.Configuration.UmbracoSettings;
using System.Linq;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -15,11 +16,7 @@ namespace Umbraco.Core.Composing.Composers
container.RegisterSingleton<IFileSystems>(factory => factory.GetInstance<FileSystems>());
// register MediaFileSystem, which can be injected directly
container.RegisterSingleton(factory => factory.GetInstance<IFileSystems>().MediaFileSystem);
// register MediaFileSystem, so that FileSystems can create it
container.Register<IFileSystem, MediaFileSystem>((f, wrappedFileSystem)
=> new MediaFileSystem(wrappedFileSystem, f.GetInstance<IContentSection>(), f.GetInstance<IMediaPathScheme>(), f.GetInstance<ILogger>()));
container.Register/*Singleton*/(factory => factory.GetInstance<IFileSystems>().MediaFileSystem);
return container;
}

View File

@@ -30,7 +30,7 @@ namespace Umbraco.Core.Composing
/// <para>Throws an exception if the container failed to get an instance of the specified type.</para>
/// <para>The arguments are used as dependencies by the container.</para>
/// </remarks>
public static T GetInstance<T>(this IContainer container, object[] args)
public static T GetInstance<T>(this IContainer container, params object[] args)
=> (T) container.GetInstance(typeof(T), args);
/// <summary>

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Umbraco.Core.Composing
{
@@ -43,7 +42,10 @@ namespace Umbraco.Core.Composing
/// <para>Throws an exception if the container failed to get an instance of the specified type.</para>
/// <para>The arguments are used as dependencies by the container.</para>
/// </remarks>
object GetInstance(Type type, object[] args);
// fixme - some restrictions:
// method is not optimized, .Invoke-ing the ctor, no compiled dynamic method
// uses the ctor with most args, always, not trying to figure out which one to use
object GetInstance(Type type, params object[] args);
/// <summary>
/// Tries to get an instance.
@@ -67,13 +69,23 @@ namespace Umbraco.Core.Composing
/// <typeparam name="TService">The type of the service.</typeparam>
IEnumerable<TService> GetAllInstances<TService>();
// fixme
/// <summary>
/// Gets registration for a service.
/// </summary>
/// <param name="serviceType">The type of the service.</param>
/// <returns>The registrations for the service.</returns>
IEnumerable<Registration> GetRegistered(Type serviceType);
#endregion
#region Registry
// notes
// when implementing IContainer, the following rules apply
// - it is possible to register a service, even after some instances of other services have been created
// - it is possible to re-register a service, as long as an instance of that service has not been created
// - once an instance of a service has been created, it is not possible to change its registration
/// <summary>
/// Registers a service as its own implementation.
/// </summary>
@@ -107,6 +119,13 @@ namespace Umbraco.Core.Composing
/// <summary>
/// Registers a base type for auto-registration.
/// </summary>
/// <remarks>
/// <para>Auto-registration means that anytime the container is asked to create an instance
/// of a type deriving from <paramref name="serviceBaseType"/>, it will first register that
/// type automatically.</para>
/// <para>This can be used for instance for views or controllers. Then, one just needs to
/// register a common base class or interface, and the container knows how to create instances.</para>
/// </remarks>
void RegisterAuto(Type serviceBaseType);
/// <summary>
@@ -114,11 +133,6 @@ namespace Umbraco.Core.Composing
/// </summary>
void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient);
// fixme - very LightInject specific? or?
// beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294
void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, TDependency> factory);
void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, object[], TDependency> factory);
#endregion
#region Control
@@ -134,6 +148,12 @@ namespace Umbraco.Core.Composing
// fixme - document all these
/// <summary>
/// Configures the container for Umbraco.
/// </summary>
/// <remarks>
/// <para></para>
/// </remarks>
IContainer ConfigureForUmbraco();
IContainer ConfigureForWeb();

View File

@@ -62,8 +62,26 @@ namespace Umbraco.Core.Composing.LightInject
=> Container.GetInstance(type, name);
/// <inheritdoc />
public object GetInstance(Type type, object[] args)
=> Container.GetInstance(type, args);
public object GetInstance(Type type, params object[] args)
{
// LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities
//return Container.GetInstance(type, args);
var ctor = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public).OrderByDescending(x => x.GetParameters().Length).FirstOrDefault();
if (ctor == null) throw new InvalidOperationException($"Could not find a public constructor for type {type.FullName}.");
var ctorParameters = ctor.GetParameters();
var ctorArgs = new object[ctorParameters.Length];
var i = 0;
foreach (var parameter in ctorParameters)
{
// no! IsInstanceOfType is not ok here
// ReSharper disable once UseMethodIsInstanceOfType
var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
ctorArgs[i++] = arg ?? GetInstance(parameter.ParameterType);
}
return ctor.Invoke(ctorArgs);
}
/// <inheritdoc />
public object TryGetInstance(Type type)
@@ -198,13 +216,16 @@ namespace Umbraco.Core.Composing.LightInject
public void RegisterOrdered(Type serviceType, Type[] implementingTypes, Lifetime lifetime = Lifetime.Transient)
=> Container.RegisterOrdered(serviceType, implementingTypes, _ => GetLifetime(lifetime));
/// <inheritdoc />
public void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, TDependency> factory)
=> Container.RegisterConstructorDependency((f, x) => factory(this, x));
/// <inheritdoc />
public void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, object[], TDependency> factory)
=> Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a));
// was the Light-Inject specific way of dealing with args, but we've replaced it with our own
// beware! does NOT work on singletons, see https://github.com/seesharper/LightInject/issues/294
//
///// <inheritdoc />
//public void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, TDependency> factory)
// => Container.RegisterConstructorDependency((f, x) => factory(this, x));
//
///// <inheritdoc />
//public void RegisterConstructorDependency<TDependency>(Func<IContainer, ParameterInfo, object[], TDependency> factory)
// => Container.RegisterConstructorDependency((f, x, a) => factory(this, x, a));
#endregion
@@ -251,9 +272,13 @@ namespace Umbraco.Core.Composing.LightInject
// if looking for a IContainer, and one was passed in args, use it
// this is for collection builders which require the IContainer
//Container.RegisterConstructorDependency((c, i, a) => a.OfType<IContainer>().FirstOrDefault());
// which means that the only way to inject the container into builders is to register it
Container.RegisterInstance<IContainer>(this);
//
// and, the block below is also disabled, because it is ugly
//
//// which means that the only way to inject the container into builders is to register it
//Container.RegisterInstance<IContainer>(this);
//
// instead, we use an explicit GetInstance with arguments implementation
return this;
}

View File

@@ -299,7 +299,7 @@ namespace Umbraco.Core.IO
var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped());
// getting the fs from the container - see FileSystemsComposer
var fs = Current.Container.GetInstance<TFileSystem>(new object[] { (IFileSystem) shadowWrapper });
var fs = Current.Container.GetInstance<TFileSystem>((IFileSystem) shadowWrapper);
_wrappers.Add(shadowWrapper); // keeping a reference to the wrapper
return fs;
});

View File

@@ -10,27 +10,12 @@ namespace Umbraco.Core.Migrations
public MigrationBuilder(IContainer container)
{
_container = container;
// because the builder should be "per container" this ctor should run only once per container.
//
// note: constructor dependencies do NOT work with lifetimes other than transient
// see https://github.com/seesharper/LightInject/issues/294
//
// resolve ctor dependency from GetInstance() runtimeArguments, if possible - 'factory' is
// the container, 'info' describes the ctor argument, and 'args' contains the args that
// were passed to GetInstance() - use first arg if it is the right type.
//
// for IMigrationContext
container.RegisterConstructorDependency((factory, info, args) => args.Length > 0 ? args[0] as IMigrationContext : null);
}
public IMigration Build(Type migrationType, IMigrationContext context)
{
// LightInject .Create() is a shortcut for .Register() + .GetInstance()
// but it does not support parameters, so we do it ourselves here
_container.Register(migrationType);
return (IMigration) _container.GetInstance(migrationType, new object[] { context });
return (IMigration) _container.GetInstance(migrationType, context);
}
}
}

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using LightInject;
using Moq;
using Newtonsoft.Json;
using NUnit.Framework;

View File

@@ -1,20 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using LightInject;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.Repositories.Implement;
using Umbraco.Core.Sync;
using Umbraco.Tests.Cache.DistributedCache;
using Umbraco.Tests.Services;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Tests.Testing;
using Umbraco.Web.Cache;
using static Umbraco.Tests.Cache.DistributedCache.DistributedCacheTests;

View File

@@ -3,17 +3,9 @@ using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Security.Cryptography;
using System.Web.Security;
using LightInject;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Core.Scoping;
using Umbraco.Core.Security;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
namespace Umbraco.Tests.Membership

View File

@@ -1,7 +1,4 @@
using System;
using System.Configuration;
using System.Linq;
using LightInject;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
@@ -11,8 +8,6 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Sync;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Cache.DistributedCache;
using Umbraco.Tests.TestHelpers.Stubs;
namespace Umbraco.Tests.Misc
@@ -75,7 +70,7 @@ namespace Umbraco.Tests.Misc
ApplicationUrlHelper.ApplicationUrlProvider = request => "http://server1.com/umbraco";
var state = new RuntimeState(Mock.Of<ILogger>(), new Lazy<IServerRegistrar>(Mock.Of<IServerRegistrar>), new Lazy<MainDom>(Mock.Of<MainDom>), settings, globalConfig.Object);
@@ -101,7 +96,7 @@ namespace Umbraco.Tests.Misc
// still NOT set
Assert.IsNull(url);
}
[Test]
public void SetApplicationUrlFromStSettingsNoSsl()
{
@@ -112,8 +107,8 @@ namespace Umbraco.Tests.Misc
var globalConfig = Mock.Get(SettingsForTests.GenerateMockGlobalSettings());
globalConfig.Setup(x => x.UseHttps).Returns(false);
var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of<ILogger>(), globalConfig.Object, Mock.Of<IServerRegistrar>());
Assert.AreEqual("http://mycoolhost.com/umbraco", url);
@@ -129,8 +124,8 @@ namespace Umbraco.Tests.Misc
var globalConfig = Mock.Get(SettingsForTests.GenerateMockGlobalSettings());
globalConfig.Setup(x => x.UseHttps).Returns(true);
var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of<ILogger>(), globalConfig.Object, Mock.Of<IServerRegistrar>());
Assert.AreEqual("https://mycoolhost.com/umbraco", url);
@@ -146,13 +141,13 @@ namespace Umbraco.Tests.Misc
var globalConfig = Mock.Get(SettingsForTests.GenerateMockGlobalSettings());
globalConfig.Setup(x => x.UseHttps).Returns(true);
var url = ApplicationUrlHelper.TryGetApplicationUrl(settings, Mock.Of<ILogger>(), globalConfig.Object, Mock.Of<IServerRegistrar>());
Assert.AreEqual("httpx://whatever.com/umbraco", url);
}
}
}

View File

@@ -6,7 +6,6 @@ using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
using LightInject;
using Umbraco.Core.Composing;
using Umbraco.Core.Persistence.Repositories.Implement;
using Umbraco.Core.PropertyEditors;

View File

@@ -1,7 +1,6 @@
using System.Web;
using System.Xml.Linq;
using System.Xml.XPath;
using Lucene.Net.Store;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
@@ -20,10 +19,8 @@ using Umbraco.Core.Strings;
using Umbraco.Examine;
using Current = Umbraco.Web.Composing.Current;
using Umbraco.Tests.Testing;
using LightInject;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
namespace Umbraco.Tests.PublishedContent
{

View File

@@ -4,8 +4,8 @@ using System.Text;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.Composers;
using Umbraco.Core.IO;
using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
@@ -23,6 +23,16 @@ namespace Umbraco.Tests.Scoping
ClearFiles();
}
protected override void ComposeApplication(bool withApplication)
{
base.ComposeApplication(withApplication);
if (!withApplication) return;
// re-register with actual media fs
Container.ComposeFileSystems();
}
public override void TearDown()
{
base.TearDown();

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Web.Routing;
using LightInject;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
@@ -14,7 +13,6 @@ using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.Repositories.Implement;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
@@ -11,7 +10,6 @@ using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.Testing;
using Umbraco.Web.Cache;
using LightInject;
using Moq;
using Umbraco.Core.Events;
using Umbraco.Core.Sync;

View File

@@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.Xml;
using Moq;
using NUnit.Framework;
using LightInject;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Events;

View File

@@ -6,6 +6,7 @@ using NUnit.Framework;
using Umbraco.Core.Models;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Composing.Composers;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.PropertyEditors;
@@ -53,6 +54,16 @@ namespace Umbraco.Tests.Services.Importing
.Add<Editor2>();
}
protected override void ComposeApplication(bool withApplication)
{
base.ComposeApplication(withApplication);
if (!withApplication) return;
// re-register with actual media fs
Container.ComposeFileSystems();
}
[Test]
public void PackagingService_Can_Import_uBlogsy_ContentTypes_And_Verify_Structure()
{

View File

@@ -26,9 +26,7 @@ using File = System.IO.File;
using Umbraco.Core.Composing;
using Umbraco.Core.Persistence.Mappers;
using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers.Stubs;
using Umbraco.Tests.Testing;
using LightInject;
using Umbraco.Core.Migrations.Install;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence.Repositories;