using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; namespace SmallInjector { /// /// A small dependency injector to demonstrate the pattern. /// public class Container : IContainer { private readonly Dictionary> _container = new Dictionary>(); /// public void RegisterType(bool isSingleton, TService instance = default) where TService : TInterface { if (!IsRegistered()) { _container[typeof(TInterface)] = new List {new RegisteredType(typeof(TService), isSingleton, null)}; } else { _container[typeof(TInterface)].Add(new RegisteredType(typeof(TService), isSingleton, null)); } } /// public void RegisterType(bool isSingleton, TService instance = default) => RegisterType(isSingleton, instance); /// public TService Resolve() => (TService) Resolve(typeof(TService)); /// public bool IsRegistered() => IsRegistered(typeof(TService)); /// public bool IsRegistered(Type serviceType) => _container.ContainsKey(serviceType); /// public IEnumerable 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; } } /// public IEnumerable ResolveAny() => ResolveAny(typeof(TService)); /// 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(); } } }