using System;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Threading;
using LightInject;
namespace Umbraco.Core.Composing.LightInject
{
///
/// Implements with LightInject.
///
public class LightInjectContainer : IContainer
{
private int _disposed;
///
/// Initializes a new instance of the with a LightInject container.
///
protected LightInjectContainer(ServiceContainer container)
{
Container = container;
}
///
/// Creates a new instance of the class.
///
public static LightInjectContainer Create()
=> new LightInjectContainer(CreateServiceContainer());
///
/// Creates a new instance of the LightInject service container.
///
protected static ServiceContainer CreateServiceContainer()
{
var container = new ServiceContainer(new ContainerOptions { EnablePropertyInjection = false });
// note: the block below is disabled, as it is too LightInject-specific
//
// supports annotated constructor injections
// eg to specify the service name on some services
//container.EnableAnnotatedConstructorInjection();
// note: the block below is disabled, we do not allow property injection at all anymore
// (see options in CreateServiceContainer)
//
// from the docs: "LightInject considers all read/write properties a dependency, but implements
// a loose strategy around property dependencies, meaning that it will NOT throw an exception
// in the case of an unresolved property dependency."
//
// in Umbraco we do NOT want to do property injection by default, so we have to disable it.
// from the docs, the following line will cause the container to "now only try to inject
// dependencies for properties that is annotated with the InjectAttribute."
//
// could not find it documented, but tests & code review shows that LightInject considers a
// property to be "injectable" when its setter exists and is not static, nor private, nor
// it is an index property. which means that eg protected or internal setters are OK.
//Container.EnableAnnotatedPropertyInjection();
// ensure that we do *not* scan assemblies
// we explicitly RegisterFrom our own composition roots and don't want them scanned
container.AssemblyScanner = new AssemblyScanner(/*container.AssemblyScanner*/);
// see notes in MixedLightInjectScopeManagerProvider
container.ScopeManagerProvider = new MixedLightInjectScopeManagerProvider();
// note: the block below is disabled, because it does not work, because collection builders
// are singletons, and constructor dependencies don't work on singletons, see
// https://github.com/seesharper/LightInject/issues/294
//
// 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().FirstOrDefault());
//
// 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(this);
//
// instead, we use an explicit GetInstance with arguments implementation
return container;
}
///
/// Gets the LightInject container.
///
protected ServiceContainer Container { get; }
///
public object ConcreteContainer => Container;
///
public void Dispose()
{
if (Interlocked.Exchange(ref _disposed, 1) == 1)
return;
Container.Dispose();
}
#region Factory
///
public object GetInstance(Type type)
=> Container.GetInstance(type);
///
public object GetInstance(Type type, string name)
=> Container.GetInstance(type, name);
///
public object TryGetInstance(Type type)
=> Container.TryGetInstance(type);
///
public IEnumerable GetAllInstances()
=> Container.GetAllInstances();
///
public IEnumerable