using System;
using System.Collections.Generic;
namespace SmallInjectorDemo
{
///
/// A small dependency injector to demonstrate the pattern.
///
public class SmallInjector
{
private readonly Dictionary _container = new Dictionary();
///
/// Register types in the resolve container.
///
/// Type of the service.
/// Type of the interface of the service.
/// True if the service should be singleton. False otherwise.
public void RegisterType(bool isSingleton)
{
_container.Add(typeof(TInterface), new RegisteredType(typeof(TService), isSingleton));
}
///
/// Register types in the resolve container.
///
/// Type of the service.
public void RegisterType(bool isSingleton) => RegisterType(isSingleton);
///
/// Resolve service of specified type.
///
/// Type of the service.
/// A instance of the service.
public TService Resolve() => (TService)Resolve(typeof(TService));
///
/// Resolve service of specified type.
///
/// Type of the service.
/// A instance of the service.
public object Resolve(Type serviceInterface)
{
if (!_container.TryGetValue(serviceInterface, out var registeredType))
{
throw new Exception("Can't resolve dependency " + serviceInterface);
}
if (registeredType.IsSingleton && registeredType.SingletonInstance != null)
return registeredType.SingletonInstance;
var constructor = registeredType.ConcreteType.GetConstructors()[0];
var parameters = constructor.GetParameters();
var constructorParameters = new object[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
{
constructorParameters[i] = Resolve(parameters[i].ParameterType);
}
if (registeredType.IsSingleton)
{
return registeredType.SingletonInstance ?? (registeredType.SingletonInstance = constructor.Invoke(constructorParameters));
}
return constructor.Invoke(constructorParameters);
}
private class RegisteredType
{
public RegisteredType(Type concreteType, bool isSingleton)
{
ConcreteType = concreteType;
IsSingleton = isSingleton;
}
public readonly bool IsSingleton;
public readonly Type ConcreteType;
public object SingletonInstance { get; set; }
}
}
}