private static void AddByConvention(this IServiceCollection serviceCollection, Action <ByConventionConfiguration> options)
        {
            if (serviceCollection == null)
            {
                throw new ArgumentNullException(nameof(serviceCollection));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var config = new ByConventionConfiguration();

            options.Invoke(config);

            foreach (Assembly assembly in config.Assemblies.Distinct())
            {
                serviceCollection.AddByConvention(assembly, config);
            }
        }
        private static void AddByConvention(this IServiceCollection serviceCollection, Assembly assembly, ByConventionConfiguration configuration)
        {
            if (serviceCollection == null)
            {
                throw new ArgumentNullException(nameof(serviceCollection));
            }
            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }

            Type[] interfaces = assembly.ExportedTypes
                                .Where(x => x.IsInterface && x.IsPublic && !configuration.IgnoredTypes.Contains(x))
                                .ToArray();
            Type[] classes = assembly.GetTypes()
                             .Where(x => !x.IsInterface && !x.IsAbstract)
                             .ToArray();

            foreach (Type @interface in interfaces)
            {
                Type[] implementations = classes
                                         .Where(@class =>
                                                @interface.IsAssignableFrom(@class) &&
                                                @interface.Assembly.Equals(@class.Assembly) &&
                                                @interface.IsInExactNamespace(@class) &&
                                                @interface.Name.Equals($"I{@class.Name}"))
                                         .ToArray();

                if (implementations.Length == 0)
                {
                    continue;
                }
                if (implementations.Length > 1)
                {
                    continue;
                }

                serviceCollection.TryAdd(new ServiceDescriptor(@interface, implementations.First(), configuration.Lifetime));
            }
        }