private void AutoRegister(TinyIoCContainer container, IEnumerable <Assembly> assemblies) { var ignoreChecks = new List <Func <Type, bool> >() { t => t.FullName.StartsWith("System.", StringComparison.Ordinal), t => t.FullName.StartsWith("Microsoft.", StringComparison.Ordinal), t => t.IsPrimitive(), t => (t.GetConstructors(BindingFlags.Instance | BindingFlags.Public).Length == 0) && !(t.IsInterface() || t.IsAbstract()), t => t.Assembly == typeof(NancyEngine).Assembly }; lock (AutoRegisterLock) { var thisType = this.GetType(); var types = assemblies.SelectMany(a => AssemblyExtensions.SafeGetTypes(a)) .Where(type => (type.DeclaringType != thisType) && !type.IsGenericTypeDefinition()) .Where(t => !ignoreChecks.Any(check => check(t))) .ToList(); var assignebleTypes = types.Where( type => type.IsClass() && (type.IsAbstract() == false) && (type != thisType)) .Select(t => { // be careful with side effects in linq container.Register(t); return(t); }) .Where(implementationType => implementationType.GetTypeInfo().ImplementedInterfaces.Any() || implementationType.BaseType != typeof(Object)) .ToList(); var abstractInterfaceTypes = types.Where(type => ((type.IsInterface() || type.IsAbstract()))); foreach (var abstractInterfaceType in abstractInterfaceTypes) { var localType = abstractInterfaceType; var implementations = assignebleTypes.Where(implementationType => localType.IsAssignableFrom(implementationType)).ToList(); if (implementations.Count > 1) { if (implementations.Count != implementations.Distinct().Count()) { var fullNamesOfDuplicatedTypes = string.Join(",\n", implementations.GroupBy(i => i).Where(j => j.Count() > 1).Select(j => j.Key.FullName)); throw new ArgumentException($"types: The same implementation type cannot be specified multiple times for {abstractInterfaceType.FullName}\n\n{fullNamesOfDuplicatedTypes}"); } foreach (var implementationType in implementations) { container.Register(abstractInterfaceType, implementationType, implementationType.FullName); } } var firstImplementation = implementations.FirstOrDefault(); if (firstImplementation != null) { container.Register(abstractInterfaceType, firstImplementation); } } } }