RaspberryIO_26/Swan/DependencyInjection/ObjectFactoryBase.cs

424 lines
15 KiB
C#
Raw Normal View History

2019-12-04 18:57:18 +01:00
namespace Swan.DependencyInjection
{
using System;
using System.Collections.Generic;
using System.Reflection;
/// <summary>
/// Represents an abstract class for Object Factory.
/// </summary>
public abstract class ObjectFactoryBase
{
/// <summary>
/// Whether to assume this factory successfully constructs its objects
///
/// Generally set to true for delegate style factories as CanResolve cannot delve
/// into the delegates they contain.
/// </summary>
public virtual bool AssumeConstruction => false;
/// <summary>
/// The type the factory instantiates.
/// </summary>
public abstract Type CreatesType { get; }
/// <summary>
/// Constructor to use, if specified.
/// </summary>
public ConstructorInfo Constructor { get; private set; }
/// <summary>
/// Gets the singleton variant.
/// </summary>
/// <value>
/// The singleton variant.
/// </value>
/// <exception cref="DependencyContainerRegistrationException">singleton.</exception>
public virtual ObjectFactoryBase SingletonVariant =>
throw new DependencyContainerRegistrationException(GetType(), "singleton");
/// <summary>
/// Gets the multi instance variant.
/// </summary>
/// <value>
/// The multi instance variant.
/// </value>
/// <exception cref="DependencyContainerRegistrationException">multi-instance.</exception>
public virtual ObjectFactoryBase MultiInstanceVariant =>
throw new DependencyContainerRegistrationException(GetType(), "multi-instance");
/// <summary>
/// Gets the strong reference variant.
/// </summary>
/// <value>
/// The strong reference variant.
/// </value>
/// <exception cref="DependencyContainerRegistrationException">strong reference.</exception>
public virtual ObjectFactoryBase StrongReferenceVariant =>
throw new DependencyContainerRegistrationException(GetType(), "strong reference");
/// <summary>
/// Gets the weak reference variant.
/// </summary>
/// <value>
/// The weak reference variant.
/// </value>
/// <exception cref="DependencyContainerRegistrationException">weak reference.</exception>
public virtual ObjectFactoryBase WeakReferenceVariant =>
throw new DependencyContainerRegistrationException(GetType(), "weak reference");
/// <summary>
/// Create the type.
/// </summary>
/// <param name="requestedType">Type user requested to be resolved.</param>
/// <param name="container">Container that requested the creation.</param>
/// <param name="options">The options.</param>
/// <returns> Instance of type. </returns>
public abstract object GetObject(
Type requestedType,
DependencyContainer container,
DependencyContainerResolveOptions options);
/// <summary>
/// Gets the factory for child container.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="parent">The parent.</param>
/// <param name="child">The child.</param>
/// <returns></returns>
public virtual ObjectFactoryBase GetFactoryForChildContainer(
Type type,
DependencyContainer parent,
DependencyContainer child)
{
return this;
}
}
/// <inheritdoc />
/// <summary>
/// IObjectFactory that creates new instances of types for each resolution.
/// </summary>
internal class MultiInstanceFactory : ObjectFactoryBase
{
private readonly Type _registerType;
private readonly Type _registerImplementation;
public MultiInstanceFactory(Type registerType, Type registerImplementation)
{
if (registerImplementation.IsAbstract || registerImplementation.IsInterface)
{
throw new DependencyContainerRegistrationException(registerImplementation,
"MultiInstanceFactory",
true);
}
if (!DependencyContainer.IsValidAssignment(registerType, registerImplementation))
{
throw new DependencyContainerRegistrationException(registerImplementation,
"MultiInstanceFactory",
true);
}
_registerType = registerType;
_registerImplementation = registerImplementation;
}
public override Type CreatesType => _registerImplementation;
public override ObjectFactoryBase SingletonVariant =>
new SingletonFactory(_registerType, _registerImplementation);
public override ObjectFactoryBase MultiInstanceVariant => this;
public override object GetObject(
Type requestedType,
DependencyContainer container,
DependencyContainerResolveOptions options)
{
try
{
return container.RegisteredTypes.ConstructType(_registerImplementation, Constructor, options);
}
catch (DependencyContainerResolutionException ex)
{
throw new DependencyContainerResolutionException(_registerType, ex);
}
}
}
/// <inheritdoc />
/// <summary>
/// IObjectFactory that invokes a specified delegate to construct the object.
/// </summary>
internal class DelegateFactory : ObjectFactoryBase
{
private readonly Type _registerType;
private readonly Func<DependencyContainer, Dictionary<string, object>, object> _factory;
public DelegateFactory(
Type registerType,
Func<DependencyContainer, Dictionary<string, object>, object> factory)
{
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
_registerType = registerType;
}
public override bool AssumeConstruction => true;
public override Type CreatesType => _registerType;
public override ObjectFactoryBase WeakReferenceVariant => new WeakDelegateFactory(_registerType, _factory);
public override ObjectFactoryBase StrongReferenceVariant => this;
public override object GetObject(
Type requestedType,
DependencyContainer container,
DependencyContainerResolveOptions options)
{
try
{
return _factory.Invoke(container, options.ConstructorParameters);
}
catch (Exception ex)
{
throw new DependencyContainerResolutionException(_registerType, ex);
}
}
}
/// <inheritdoc />
/// <summary>
/// IObjectFactory that invokes a specified delegate to construct the object
/// Holds the delegate using a weak reference.
/// </summary>
internal class WeakDelegateFactory : ObjectFactoryBase
{
private readonly Type _registerType;
private readonly WeakReference _factory;
public WeakDelegateFactory(
Type registerType,
Func<DependencyContainer, Dictionary<string, object>, object> factory)
{
if (factory == null)
throw new ArgumentNullException(nameof(factory));
_factory = new WeakReference(factory);
_registerType = registerType;
}
public override bool AssumeConstruction => true;
public override Type CreatesType => _registerType;
public override ObjectFactoryBase StrongReferenceVariant
{
get
{
if (!(_factory.Target is Func<DependencyContainer, Dictionary<string, object>, object> factory))
throw new DependencyContainerWeakReferenceException(_registerType);
return new DelegateFactory(_registerType, factory);
}
}
public override ObjectFactoryBase WeakReferenceVariant => this;
public override object GetObject(
Type requestedType,
DependencyContainer container,
DependencyContainerResolveOptions options)
{
if (!(_factory.Target is Func<DependencyContainer, Dictionary<string, object>, object> factory))
throw new DependencyContainerWeakReferenceException(_registerType);
try
{
return factory.Invoke(container, options.ConstructorParameters);
}
catch (Exception ex)
{
throw new DependencyContainerResolutionException(_registerType, ex);
}
}
}
/// <summary>
/// Stores an particular instance to return for a type.
/// </summary>
internal class InstanceFactory : ObjectFactoryBase, IDisposable
{
private readonly Type _registerType;
private readonly Type _registerImplementation;
private readonly object _instance;
public InstanceFactory(Type registerType, Type registerImplementation, object instance)
{
if (!DependencyContainer.IsValidAssignment(registerType, registerImplementation))
throw new DependencyContainerRegistrationException(registerImplementation, "InstanceFactory", true);
_registerType = registerType;
_registerImplementation = registerImplementation;
_instance = instance;
}
public override bool AssumeConstruction => true;
public override Type CreatesType => _registerImplementation;
public override ObjectFactoryBase MultiInstanceVariant =>
new MultiInstanceFactory(_registerType, _registerImplementation);
public override ObjectFactoryBase WeakReferenceVariant =>
new WeakInstanceFactory(_registerType, _registerImplementation, _instance);
public override ObjectFactoryBase StrongReferenceVariant => this;
public override object GetObject(
Type requestedType,
DependencyContainer container,
DependencyContainerResolveOptions options)
{
return _instance;
}
public void Dispose()
{
var disposable = _instance as IDisposable;
disposable?.Dispose();
}
}
/// <summary>
/// Stores the instance with a weak reference.
/// </summary>
internal class WeakInstanceFactory : ObjectFactoryBase, IDisposable
{
private readonly Type _registerType;
private readonly Type _registerImplementation;
private readonly WeakReference _instance;
public WeakInstanceFactory(Type registerType, Type registerImplementation, object instance)
{
if (!DependencyContainer.IsValidAssignment(registerType, registerImplementation))
{
throw new DependencyContainerRegistrationException(
registerImplementation,
"WeakInstanceFactory",
true);
}
_registerType = registerType;
_registerImplementation = registerImplementation;
_instance = new WeakReference(instance);
}
public override Type CreatesType => _registerImplementation;
public override ObjectFactoryBase MultiInstanceVariant =>
new MultiInstanceFactory(_registerType, _registerImplementation);
public override ObjectFactoryBase WeakReferenceVariant => this;
public override ObjectFactoryBase StrongReferenceVariant
{
get
{
var instance = _instance.Target;
if (instance == null)
throw new DependencyContainerWeakReferenceException(_registerType);
return new InstanceFactory(_registerType, _registerImplementation, instance);
}
}
public override object GetObject(
Type requestedType,
DependencyContainer container,
DependencyContainerResolveOptions options)
{
var instance = _instance.Target;
if (instance == null)
throw new DependencyContainerWeakReferenceException(_registerType);
return instance;
}
public void Dispose() => (_instance.Target as IDisposable)?.Dispose();
}
/// <summary>
/// A factory that lazy instantiates a type and always returns the same instance.
/// </summary>
internal class SingletonFactory : ObjectFactoryBase, IDisposable
{
private readonly Type _registerType;
private readonly Type _registerImplementation;
private readonly object _singletonLock = new object();
private object _current;
public SingletonFactory(Type registerType, Type registerImplementation)
{
if (registerImplementation.IsAbstract || registerImplementation.IsInterface)
{
throw new DependencyContainerRegistrationException(registerImplementation, nameof(SingletonFactory), true);
}
if (!DependencyContainer.IsValidAssignment(registerType, registerImplementation))
{
throw new DependencyContainerRegistrationException(registerImplementation, nameof(SingletonFactory), true);
}
_registerType = registerType;
_registerImplementation = registerImplementation;
}
public override Type CreatesType => _registerImplementation;
public override ObjectFactoryBase SingletonVariant => this;
public override ObjectFactoryBase MultiInstanceVariant =>
new MultiInstanceFactory(_registerType, _registerImplementation);
public override object GetObject(
Type requestedType,
DependencyContainer container,
DependencyContainerResolveOptions options)
{
if (options.ConstructorParameters.Count != 0)
throw new ArgumentException("Cannot specify parameters for singleton types");
lock (_singletonLock)
{
if (_current == null)
_current = container.RegisteredTypes.ConstructType(_registerImplementation, Constructor, options);
}
return _current;
}
public override ObjectFactoryBase GetFactoryForChildContainer(
Type type,
DependencyContainer parent,
DependencyContainer child)
{
// We make sure that the singleton is constructed before the child container takes the factory.
// Otherwise the results would vary depending on whether or not the parent container had resolved
// the type before the child container does.
GetObject(type, parent, DependencyContainerResolveOptions.Default);
return this;
}
public void Dispose() => (_current as IDisposable)?.Dispose();
}
}