Netcore: Alternate approach for MSDI refactor (#9247)
* Doesn't make much sense to have Concrete on IRegister, only on IFactory * Handle FilesTreeController requires IFileSystem of type PhysicalFileSystem * Handle registration of default MediaFileSystem without using RegisterUniqueFor * Remove RegisterFor / RegisterUniqueFor from IRegister * Switch over from LightInject to wrappers around MSDI * Made mapper dependencies more explicit * Remove registration for AngularJsonMediaTypeFormatter It's dependencies aren't registered so container validation fails * Resolve lifetime issue for EnsureValidSessionId by service locating else resolve scoped in singleton * Make registration more explicit for backoffice UserManager * Make install step registrations more explicit * Disable service provider validation so site can launch Maybe this is a problem maybe not, we build about 8000 service providers so maybe everything is fine later... * Further cleanup of IFactory interface * Further cleanup of IRegister interface * Revert "Make registration more explicit for backoffice UserManager" This reverts commit 7215fe836103c597cd0873c66737a79b91ed4c49. * Resolve issue where NewInstallStep would fail to reset password for "SuperUser" Before MSDI, somehow BackOfficeIdentityOptions would be configured with token provider map from IdentityBuilder.AddDefaultTokenProviders. After switchover those config actions are lost. Subclass IdentityBuilder to ensure BackOfficeIdentityOptions doesn't miss config setup upstream. * Initialize current. * Add todo to turn container validation back on. * Migrated ScopeFileSystemsTests to integration tests Signed-off-by: Bjarke Berg <mail@bergmania.dk> * Resolve issue where MediaFileSystem was skipping ShadowFileSystem * Attempt to fix ScopeFileSystemsTests on azure devops Signed-off-by: Bjarke Berg <mail@bergmania.dk> * Be interesting to know what the actual full path is in pipeline. * Clarify intent of CreateMediaTest Doesn't help resolve weird UnauthorizedAccessException but it cuts so much cognitive overhead for the future. * Use ILoggerfactory rather than mock for the manually constructed file PhysicalFileSystem * Maybe resolve failing test on azure pipeline. Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
@@ -64,10 +64,7 @@ namespace Umbraco.Core.Composing
|
||||
#endregion
|
||||
|
||||
#region IRegister
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Concrete => _register.Concrete;
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Register(Type serviceType, Lifetime lifetime = Lifetime.Transient)
|
||||
=> _register.Register(serviceType, lifetime);
|
||||
@@ -85,33 +82,6 @@ namespace Umbraco.Core.Composing
|
||||
public void Register(Type serviceType, object instance)
|
||||
=> _register.Register(serviceType, instance);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterFor<TService, TTarget>(Lifetime lifetime = Lifetime.Transient)
|
||||
where TService : class
|
||||
=> _register.RegisterFor<TService, TTarget>(lifetime);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterFor<TService, TTarget>(Type implementingType, Lifetime lifetime = Lifetime.Transient)
|
||||
where TService : class
|
||||
=> _register.RegisterFor<TService, TTarget>(implementingType, lifetime);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterFor<TService, TTarget>(Func<IFactory, TService> factory, Lifetime lifetime = Lifetime.Transient)
|
||||
where TService : class
|
||||
=> _register.RegisterFor<TService, TTarget>(factory, lifetime);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterFor<TService, TTarget>(TService instance)
|
||||
where TService : class
|
||||
=> _register.RegisterFor<TService, TTarget>(instance);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterAuto(Type serviceBaseType)
|
||||
=> _register.RegisterAuto(serviceBaseType);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ConfigureForWeb()
|
||||
=> _register.ConfigureForWeb();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IFactory CreateFactory()
|
||||
@@ -127,13 +97,7 @@ namespace Umbraco.Core.Composing
|
||||
builder.RegisterWith(_register);
|
||||
_builders.Clear(); // no point keep them around
|
||||
|
||||
IFactory factory = null;
|
||||
|
||||
// ReSharper disable once AccessToModifiedClosure -- on purpose
|
||||
_register.Register(_ => factory, Lifetime.Singleton);
|
||||
factory = _register.CreateFactory();
|
||||
|
||||
return factory;
|
||||
return _register.CreateFactory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -186,38 +150,6 @@ namespace Umbraco.Core.Composing
|
||||
public void RegisterUnique(Type serviceType, object instance)
|
||||
=> _uniques[GetUniqueName(serviceType)] = register => register.Register(serviceType, instance);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a unique service for a target, as its own implementation.
|
||||
/// </summary>
|
||||
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
|
||||
public void RegisterUniqueFor<TService, TTarget>()
|
||||
where TService : class
|
||||
=> _uniques[GetUniqueName<TService, TTarget>()] = register => register.RegisterFor<TService, TTarget>(Lifetime.Singleton);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a unique service for a target, with an implementing type.
|
||||
/// </summary>
|
||||
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
|
||||
public void RegisterUniqueFor<TService, TTarget>(Type implementingType)
|
||||
where TService : class
|
||||
=> _uniques[GetUniqueName<TService, TTarget>()] = register => register.RegisterFor<TService, TTarget>(implementingType, Lifetime.Singleton);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a unique service for a target, with an implementation factory.
|
||||
/// </summary>
|
||||
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
|
||||
public void RegisterUniqueFor<TService, TTarget>(Func<IFactory, TService> factory)
|
||||
where TService : class
|
||||
=> _uniques[GetUniqueName<TService, TTarget>()] = register => register.RegisterFor<TService, TTarget>(factory, Lifetime.Singleton);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a unique service for a target, with an implementing instance.
|
||||
/// </summary>
|
||||
/// <remarks>Unique services have one single implementation, and a Singleton lifetime.</remarks>
|
||||
public void RegisterUniqueFor<TService, TTarget>(TService instance)
|
||||
where TService : class
|
||||
=> _uniques[GetUniqueName<TService, TTarget>()] = register => register.RegisterFor<TService, TTarget>(instance);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Collection Builders
|
||||
|
||||
@@ -21,15 +21,6 @@ namespace Umbraco.Core.Composing
|
||||
/// <remarks>Throws an exception if the container failed to get an instance of the specified type.</remarks>
|
||||
object GetInstance(Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a targeted instance of a service.
|
||||
/// </summary>
|
||||
/// <typeparam name="TService">The type of the service.</typeparam>
|
||||
/// <typeparam name="TTarget">The type of the target.</typeparam>
|
||||
/// <returns>The instance of the specified type for the specified target.</returns>
|
||||
/// <remarks>Throws an exception if the container failed to get an instance of the specified type.</remarks>
|
||||
TService GetInstanceFor<TService, TTarget>();
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get an instance of a service.
|
||||
/// </summary>
|
||||
@@ -52,18 +43,7 @@ namespace Umbraco.Core.Composing
|
||||
/// <typeparam name="TService">The type of the service.</typeparam>
|
||||
IEnumerable<TService> GetAllInstances<TService>()
|
||||
where TService : class;
|
||||
|
||||
/// <summary>
|
||||
/// Releases an instance.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance.</param>
|
||||
/// <remarks>
|
||||
/// See https://stackoverflow.com/questions/14072208 and http://kozmic.net/2010/08/27/must-i-release-everything-when-using-windsor/,
|
||||
/// you only need to release instances you specifically resolved, and even then, if done right, that might never be needed. For
|
||||
/// instance, LightInject does not require this and does not support it - should work with scopes.
|
||||
/// </remarks>
|
||||
void Release(object instance);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Begins a scope.
|
||||
/// </summary>
|
||||
@@ -72,13 +52,5 @@ namespace Umbraco.Core.Composing
|
||||
/// <para>Scopes can be nested. Each instance is disposed individually.</para>
|
||||
/// </remarks>
|
||||
IDisposable BeginScope();
|
||||
|
||||
/// <summary>
|
||||
/// Enables per-request scope.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Ties scopes to web requests.</para>
|
||||
/// </remarks>
|
||||
void EnablePerWebRequestScope();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,6 @@ namespace Umbraco.Core.Composing
|
||||
/// </summary>
|
||||
public interface IRegister
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the concrete container.
|
||||
/// </summary>
|
||||
object Concrete { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Registers a service as its own implementation.
|
||||
/// </summary>
|
||||
@@ -33,69 +28,8 @@ namespace Umbraco.Core.Composing
|
||||
/// </summary>
|
||||
void Register(Type serviceType, object instance);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a service for a target, as its own implementation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// There can only be one implementation or instanced registered for a service and target;
|
||||
/// what happens if many are registered is not specified.
|
||||
/// </remarks>
|
||||
void RegisterFor<TService, TTarget>(Lifetime lifetime = Lifetime.Transient)
|
||||
where TService : class;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a service for a target, with an implementation type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// There can only be one implementation or instanced registered for a service and target;
|
||||
/// what happens if many are registered is not specified.
|
||||
/// </remarks>
|
||||
void RegisterFor<TService, TTarget>(Type implementingType, Lifetime lifetime = Lifetime.Transient)
|
||||
where TService : class;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a service for a target, with an implementation factory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// There can only be one implementation or instanced registered for a service and target;
|
||||
/// what happens if many are registered is not specified.
|
||||
/// </remarks>
|
||||
void RegisterFor<TService, TTarget>(Func<IFactory, TService> factory, Lifetime lifetime = Lifetime.Transient)
|
||||
where TService : class;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a service for a target, with an implementing instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// There can only be one implementation or instanced registered for a service and target;
|
||||
/// what happens if many are registered is not specified.
|
||||
/// </remarks>
|
||||
void RegisterFor<TService, TTarget>(TService instance)
|
||||
where TService : class;
|
||||
|
||||
/// <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);
|
||||
|
||||
#region Control
|
||||
|
||||
/// <summary>
|
||||
/// Configures the container for web support.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Enables support for MVC, WebAPI, but *not* per-request scope. This is used early in the boot
|
||||
/// process, where anything "scoped" should not be linked to a web request.</para>
|
||||
/// </remarks>
|
||||
void ConfigureForWeb(); // TODO: Unsure if we need this anymore
|
||||
|
||||
/// <summary>
|
||||
/// Creates the factory.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for targeted service factories.
|
||||
/// </summary>
|
||||
/// <typeparam name="TService"></typeparam>
|
||||
public abstract class TargetedServiceFactory<TService>
|
||||
{
|
||||
private readonly IFactory _factory;
|
||||
|
||||
protected TargetedServiceFactory(IFactory factory)
|
||||
{
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
public TService For<TTarget>() => _factory.GetInstanceFor<TService, TTarget>();
|
||||
}
|
||||
}
|
||||
@@ -19,13 +19,6 @@ namespace Umbraco.Core
|
||||
public static void RegisterUnique<TService, TImplementing>(this Composition composition)
|
||||
=> composition.RegisterUnique(typeof(TService), typeof(TImplementing));
|
||||
|
||||
/// <summary>
|
||||
/// Registers a unique service with an implementation type, for a target.
|
||||
/// </summary>
|
||||
public static void RegisterUniqueFor<TService, TTarget, TImplementing>(this Composition composition)
|
||||
where TService : class
|
||||
=> composition.RegisterUniqueFor<TService, TTarget>(typeof(TImplementing));
|
||||
|
||||
/// <summary>
|
||||
/// Registers a unique service with an implementing instance.
|
||||
/// </summary>
|
||||
|
||||
@@ -282,7 +282,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
lock (_shadowLocker)
|
||||
{
|
||||
var wrapper = new ShadowWrapper(filesystem, _ioHelper, _hostingEnvironment, _loggerFactory, shadowPath, IsScoped);
|
||||
var wrapper = new ShadowWrapper(filesystem, _ioHelper, _hostingEnvironment, _loggerFactory, shadowPath,() => IsScoped());
|
||||
if (_shadowCurrentId != null)
|
||||
wrapper.Shadow(_shadowCurrentId);
|
||||
_shadowWrappers.Add(wrapper);
|
||||
|
||||
@@ -10,7 +10,8 @@ using Umbraco.Core.Hosting;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
public class PhysicalFileSystem : IFileSystem
|
||||
public interface IPhysicalFileSystem : IFileSystem {}
|
||||
public class PhysicalFileSystem : IPhysicalFileSystem
|
||||
{
|
||||
private readonly IIOHelper _ioHelper;
|
||||
private readonly ILogger<PhysicalFileSystem> _logger;
|
||||
@@ -56,7 +57,6 @@ namespace Umbraco.Core.IO
|
||||
if (string.IsNullOrEmpty(rootUrl)) throw new ArgumentException("Value can't be empty.", nameof(rootUrl));
|
||||
if (rootPath.StartsWith("~/")) throw new ArgumentException("Value can't be a virtual path and start with '~/'.", nameof(rootPath));
|
||||
|
||||
|
||||
// rootPath should be... rooted, as in, it's a root path!
|
||||
if (Path.IsPathRooted(rootPath) == false)
|
||||
{
|
||||
@@ -65,6 +65,9 @@ namespace Umbraco.Core.IO
|
||||
rootPath = Path.Combine(localRoot, rootPath);
|
||||
}
|
||||
|
||||
// clean up root path
|
||||
rootPath = Path.GetFullPath(rootPath);
|
||||
|
||||
_rootPath = EnsureDirectorySeparatorChar(rootPath).TrimEnd(Path.DirectorySeparatorChar);
|
||||
_rootPathFwd = EnsureUrlSeparatorChar(_rootPath);
|
||||
_rootUrl = EnsureUrlSeparatorChar(rootUrl).TrimEnd('/');
|
||||
@@ -328,7 +331,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
// nothing prevents us to reach the file, security-wise, yet it is outside
|
||||
// this filesystem's root - throw
|
||||
throw new UnauthorizedAccessException("File '" + opath + "' is outside this filesystem's root.");
|
||||
throw new UnauthorizedAccessException($"File original: [{opath}] full: [{path}] is outside this filesystem's root.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
public class SupportingFileSystems : TargetedServiceFactory<IFileSystem>
|
||||
{
|
||||
public SupportingFileSystems(IFactory factory)
|
||||
: base(factory)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,6 @@ namespace Umbraco.Core
|
||||
public static void Register<TService, TImplementing>(this IRegister register, Lifetime lifetime = Lifetime.Transient)
|
||||
=> register.Register(typeof(TService), typeof(TImplementing), lifetime);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a service with an implementation type, for a target.
|
||||
/// </summary>
|
||||
public static void RegisterFor<TService, TImplementing, TTarget>(this IRegister register, Lifetime lifetime = Lifetime.Transient)
|
||||
where TService : class
|
||||
=> register.RegisterFor<TService, TTarget>(typeof(TImplementing), lifetime);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a service as its own implementation.
|
||||
/// </summary>
|
||||
@@ -33,12 +26,5 @@ namespace Umbraco.Core
|
||||
public static void Register<TService>(this IRegister register, TService instance)
|
||||
where TService : class
|
||||
=> register.Register(typeof(TService), instance);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a base type for auto-registration.
|
||||
/// </summary>
|
||||
public static void RegisterAuto<TServiceBase>(this IRegister register)
|
||||
where TServiceBase : class
|
||||
=> register.RegisterAuto(typeof(TServiceBase));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user