Holger Börchers 291eafeeba
All checks were successful
build (7.0.x)
added unit tests
2023-03-29 21:47:10 +02:00

91 lines
3.2 KiB
C#

namespace SmallInjector;
/// <summary>
/// A small dependency injector to demonstrate the pattern.
/// </summary>
public class Container : IContainer
{
private readonly Dictionary<Type, List<RegisteredType>> _container = new();
/// <inheritdoc/>
public void RegisterType<TService, TInterface>(bool isSingleton, TService instance = default) where TService : TInterface
{
if (!IsRegistered<TInterface>())
{
_container[typeof(TInterface)] = new List<RegisteredType> { new RegisteredType(typeof(TService), isSingleton, null) };
}
else
{
_container[typeof(TInterface)].Add(new RegisteredType(typeof(TService), isSingleton, null));
}
}
/// <inheritdoc/>
public void RegisterType<TService>(bool isSingleton, TService instance = default) => RegisterType<TService, TService>(isSingleton, instance);
/// <inheritdoc/>
public TService Resolve<TService>() => (TService)Resolve(typeof(TService));
/// <inheritdoc />
public bool IsRegistered<TService>() => IsRegistered(typeof(TService));
/// <inheritdoc />
public bool IsRegistered(Type serviceType) => _container.ContainsKey(serviceType);
/// <inheritdoc />
public IEnumerable<object> ResolveAny(Type serviceType)
{
if (!_container.TryGetValue(serviceType, out var registeredTypes))
throw new Exception($"Dependency {serviceType.FullName} is not registered");
foreach (var registeredType in registeredTypes)
{
if (registeredType.IsSingleton && registeredType.Instance != null)
{
yield return registeredType.Instance;
continue;
}
var constructor = registeredType.ServiceType.GetConstructors()[0];
var parameters = constructor.GetParameters();
var constructorParameters = new object[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
{
var parameterType = parameters[i].ParameterType;
if (typeof(Array).IsAssignableFrom(parameterType))
{
constructorParameters[i] = ResolveAny(parameterType.GetElementType()).ToArray();
}
else
{
constructorParameters[i] = Resolve(parameters[i].ParameterType);
}
}
var instance = constructor.Invoke(constructorParameters);
yield return registeredType.IsSingleton ? (registeredType.Instance = instance) : instance;
}
}
/// <inheritdoc />
public IEnumerable<object> ResolveAny<TService>() => ResolveAny(typeof(TService));
/// <inheritdoc/>
public object Resolve(Type serviceType) => ResolveAny(serviceType).First();
private class RegisteredType
{
public bool IsSingleton { get; }
public Type ServiceType { get; }
public object Instance { get; set; }
public RegisteredType(Type serviceType, bool isSingleton, object instance)
{
ServiceType = serviceType;
IsSingleton = isSingleton;
Instance = instance;
}
public override string ToString() => ServiceType.ToString();
}
}