Dictionary params & error handling

This commit is contained in:
Lars-Erik Aabech
2018-09-02 22:09:37 +02:00
committed by Lars-Erik Aabech
parent 70d93d4668
commit bc80affcf1
7 changed files with 69 additions and 15 deletions

View File

@@ -19,6 +19,17 @@ namespace Umbraco.Core.Composing
public static T GetInstance<T>(this IContainer container)
=> (T) container.GetInstance(typeof(T));
/// <summary>
/// Gets a named instance.
/// </summary>
/// <typeparam name="T">The type of the instance.</typeparam>
/// <param name="container">The container.</param>
/// <param name="name">The name of the instance.</typeparam>
/// <returns>An instance of the specified type and name.</returns>
/// <remarks>Throws an exception if the container failed to get an instance of the specified type.</remarks>
public static T GetInstance<T>(this IContainer container, string name)
=> (T) container.GetInstance(typeof(T), name);
/// <summary>
/// Tries to get an instance.
/// </summary>
@@ -49,7 +60,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 CreateInstance<T>(this IContainer container, params object[] args)
public static T CreateInstance<T>(this IContainer container, IDictionary<string, object> args)
=> (T) container.CreateInstance(typeof(T), args);
/// <summary>
@@ -64,6 +75,12 @@ namespace Umbraco.Core.Composing
public static void Register<TService, TImplementing>(this IContainer container, string name, Lifetime lifetime = Lifetime.Transient)
=> container.Register(typeof(TService), typeof(TImplementing), name, lifetime);
/// <summary>
/// Registers a service with a named implementation type and factory.
/// </summary>
public static void Register<TService, TImplementing>(this IContainer container, string name, Func<IContainer, TService> factory, Lifetime lifetime = Lifetime.Transient)
=> container.Register(factory, name, lifetime);
/// <summary>
/// Registers a service as its own implementation.
/// </summary>
@@ -112,8 +129,8 @@ namespace Umbraco.Core.Composing
if (container.GetRegistered<TBuilder>().Any())
throw new InvalidOperationException("Collection builders should be registered only once.");
// register the builder - passing the container as an arg to the factory
container.RegisterSingleton(c => c.CreateInstance<TBuilder>(container));
// register the builder
container.RegisterSingleton<TBuilder>();
// initialize and return the builder
return container.GetInstance<TBuilder>();

View File

@@ -70,14 +70,14 @@ namespace Umbraco.Core.Composing
/// Creates an instance with arguments.
/// </summary>
/// <param name="type">The type of the instance.</param>
/// <param name="args">Arguments.</param>
/// <param name="args">Named arguments.</param>
/// <returns>An instance of the specified type.</returns>
/// <remarks>
/// <para>The instance type does not need to be registered into the container.</para>
/// <para>The arguments are used as dependencies by the container. Other dependencies
/// are retrieved from the container.</para>
/// </remarks>
object CreateInstance(Type type, params object[] args);
object CreateInstance(Type type, IDictionary<string, object> args);
#endregion
@@ -104,6 +104,11 @@ namespace Umbraco.Core.Composing
/// </summary>
void Register(Type serviceType, Type implementingType, string name, Lifetime lifetime = Lifetime.Transient);
/// <summary>
/// Registers a named service with an implementation factory.
/// </summary>
void Register<TService>(Func<IContainer, TService> factory, string name, Lifetime lifetime = Lifetime.Transient);
/// <summary>
/// Registers a service with an implementation factory.
/// </summary>

View File

@@ -126,7 +126,7 @@ namespace Umbraco.Core.Composing.LightInject
=> Container.AvailableServices.Where(x => x.ServiceType == type).Select(x => new Registration(x.ServiceType, x.ServiceName));
/// <inheritdoc />
public object CreateInstance(Type type, params object[] args)
public object CreateInstance(Type type, IDictionary<string, object> args)
{
// LightInject has this, but then it requires RegisterConstructorDependency etc and has various oddities
// including the most annoying one, which is that it does not work on singletons (hard to fix)
@@ -146,7 +146,7 @@ namespace Umbraco.Core.Composing.LightInject
{
// no! IsInstanceOfType is not ok here
// ReSharper disable once UseMethodIsInstanceOfType
var arg = args?.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
var arg = args?.Values.FirstOrDefault(a => parameter.ParameterType.IsAssignableFrom(a.GetType()));
ctorArgs[i++] = arg ?? GetInstance(parameter.ParameterType);
}
return ctor.Invoke(ctorArgs);
@@ -234,6 +234,24 @@ namespace Umbraco.Core.Composing.LightInject
}
}
/// <inheritdoc />
public void Register<TService>(Func<IContainer, TService> factory, string name, Lifetime lifetime = Lifetime.Transient)
{
switch (lifetime)
{
case Lifetime.Transient:
case Lifetime.Request:
case Lifetime.Scope:
Container.Register(f => factory(this), name, GetLifetime(lifetime));
break;
case Lifetime.Singleton:
Container.RegisterSingleton(f => factory(this), name);
break;
default:
throw new NotSupportedException($"Lifetime {lifetime} is not supported.");
}
}
private ILifetime GetLifetime(Lifetime lifetime)
{
switch (lifetime)

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.CreateInstance<TFileSystem>((IFileSystem) shadowWrapper);
var fs = Current.Container.CreateInstance<TFileSystem>(new Dictionary<string, object>{{ "wrapped", (IFileSystem) shadowWrapper }});
_wrappers.Add(shadowWrapper); // keeping a reference to the wrapper
return fs;
});

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Composing;
namespace Umbraco.Core.Migrations
@@ -14,7 +15,7 @@ namespace Umbraco.Core.Migrations
public IMigration Build(Type migrationType, IMigrationContext context)
{
return (IMigration) _container.CreateInstance(migrationType, context);
return (IMigration) _container.CreateInstance(migrationType, new Dictionary<string, object>{{"context", context}});
}
}
}

View File

@@ -1,4 +1,5 @@
using NUnit.Framework;
using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Core.Composing;
namespace Umbraco.Tests.Composing
@@ -46,7 +47,7 @@ namespace Umbraco.Tests.Composing
public void CanRegisterSingletonWithCreate()
{
var container = CreateContainer();
container.RegisterSingleton(c => c.CreateInstance<TestClass3>(new TestClass1()));
container.RegisterSingleton(c => c.CreateInstance<TestClass3>(new Dictionary<string, object>{{"c", new TestClass1()}}));
var s1 = container.GetInstance<TestClass3>();
var s2 = container.GetInstance<TestClass3>();
Assert.AreSame(s1, s2);

View File

@@ -1,4 +1,5 @@
using System.Web;
using System;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Composing;
@@ -16,9 +17,20 @@ namespace Umbraco.Web.Composing
/// <inheritdoc />
public void Init(HttpApplication context)
{
// using the service locator here - no other way, really
Module = Current.Container.GetInstance<TModule>();
Module.Init(context);
try
{
// using the service locator here - no other way, really
Module = Current.Container.GetInstance<TModule>();
Module.Init(context);
}
catch
{
var runtimeState = Current.Container.GetInstance<IRuntimeState>();
if (runtimeState.BootFailedException != null)
{
throw new Exception("Failed to boot", runtimeState.BootFailedException);
}
}
}
/// <inheritdoc />