internal object Resolve(Type dependency, string name = null) { Implementation[] impls; object result = null; int currThreadId = Thread.CurrentThread.ManagedThreadId; if (!recursionControlStackByThreadId .TryGetValue(currThreadId, out Stack <Type> atResolvingTypes)) { atResolvingTypes = new Stack <Type>(); if (!recursionControlStackByThreadId.TryAdd(currThreadId, atResolvingTypes)) { throw new ApplicationException(); } } else { //check recursion dependency if (atResolvingTypes.Contains(dependency)) { //try create it by constroctor result = CreateByConstructor(dependency); if (result != null) { return(result); } throw new ArgumentException("Depedencies are recursive."); } } atResolvingTypes.Push(dependency); if (dependency.IsPrimitive || !dependency.IsClass && !dependency.IsInterface) //isenum, isStruct { result = Activator.CreateInstance(dependency); } else if (typeof(IEnumerable).IsAssignableFrom(dependency)) { Type dependencyType = dependency.GetGenericArguments()[0]; impls = Configuration.GetImplementations(dependencyType).ToArray(); //create array of Ts (when dependency is IEnumerable<T>) var implInstances = (object[])Activator.CreateInstance(dependencyType.MakeArrayType(), new object[] { impls.Count() }); for (int i = 0; i < impls.Count(); i++) { implInstances[i] = impls[i].ResolveOrReturnSingletonInstance(this, name); } result = implInstances; } else { impls = Configuration.GetImplementations(dependency)?.ToArray(); if (impls == null && dependency.IsGenericType)//handle search for open generic types impls as well { impls = Configuration.GetImplementations(dependency.GetGenericTypeDefinition())?.ToArray(); } if (impls != null) { Implementation implToUse = impls.First(); if (name != null) { implToUse = Array.Find(impls, impl => impl.Name == name); } result = implToUse?.ResolveOrReturnSingletonInstance(this, name); //TODO: resolve dependency on GenericType of impl of open generic dependency } else //no implementation for that dependency, try make its instance { result = CreateByConstructor(dependency); } } atResolvingTypes.Pop(); return(result); }