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; } } } }