private IEnumerable <Type> GetTypesToRegisterInternal(
     Type serviceType, IEnumerable <Assembly> assemblies, TypesToRegisterOptions options) =>
 from assembly in assemblies.Distinct()
     where !assembly.IsDynamic
 from type in GetTypesFromAssembly(assembly)
     where Types.IsConcreteType(type)
     where options.IncludeGenericTypeDefinitions || !type.IsGenericTypeDefinition()
     where Types.ServiceIsAssignableFromImplementation(serviceType, type)
 let ctor = this.SelectImplementationTypeConstructorOrNull(type)
                where ctor is null || options.IncludeDecorators || !Types.IsDecorator(serviceType, ctor)
                where ctor is null || options.IncludeComposites || !Types.IsComposite(serviceType, ctor)
            select type;
        /// <summary>
        /// Returns all concrete types that are located in the supplied <paramref name="assemblies"/>
        /// and implement or inherit from the supplied <paramref name="serviceType"/> and match the specified
        /// <paramref name="options."/>. <paramref name="serviceType"/> can be an open-generic type.
        /// </summary>
        /// <remarks>
        /// Use this method when you need influence the types that are registered using
        /// <see cref="Register(System.Type, IEnumerable{System.Reflection.Assembly})">Register</see>.
        /// The <b>Register</b> overloads that take a collection of <see cref="Assembly"/>
        /// objects use this method internally to get the list of types that need to be registered. Instead of
        /// calling  such overload, you can call an overload that takes a list of <see cref="System.Type"/> objects
        /// and pass  in a filtered result from this <b>GetTypesToRegister</b> method.
        /// <code lang="cs"><![CDATA[
        /// var container = new Container();
        ///
        /// var assemblies = new[] { typeof(ICommandHandler<>).Assembly };
        /// var options = new TypesToRegisterOptions { IncludeGenericTypeDefinitions: true };
        /// var types = container.GetTypesToRegister(typeof(ICommandHandler<>), assemblies, options)
        ///     .Where(type => !type.IsPublic);
        ///
        /// container.Register(typeof(ICommandHandler<>), types);
        /// ]]></code>
        /// This example calls the <b>GetTypesToRegister</b> method to request a list of concrete implementations
        /// of the <b>ICommandHandler&lt;T&gt;</b> interface from the assembly of that interface. After that
        /// all internal types are filtered out. This list is supplied to the
        /// <see cref="Container.Register(System.Type,IEnumerable{System.Type})">Register(Type, IEnumerable&lt;Type&gt;)</see>
        /// overload to finish the registration.
        /// </remarks>
        /// <param name="serviceType">The base type or interface to find derived types for. This can be both
        /// a non-generic and open-generic type.</param>
        /// <param name="assemblies">A list of assemblies that will be searched.</param>
        /// <param name="options">The options.</param>
        /// <returns>A collection of types.</returns>
        /// <exception cref="ArgumentNullException">Thrown when one of the arguments contain a null reference
        /// (Nothing in VB).</exception>
        public IEnumerable <Type> GetTypesToRegister(Type serviceType, IEnumerable <Assembly> assemblies,
                                                     TypesToRegisterOptions options)
        {
            Requires.IsNotNull(serviceType, nameof(serviceType));
            Requires.IsNotNull(assemblies, nameof(assemblies));
            Requires.IsNotNull(options, nameof(options));
            Requires.IsNotPartiallyClosed(serviceType, nameof(serviceType));

            var types =
                from assembly in assemblies.Distinct()
                where !assembly.IsDynamic
                from type in GetTypesFromAssembly(assembly)
                where Types.IsConcreteType(type)
                where options.IncludeGenericTypeDefinitions || !type.IsGenericTypeDefinition()
                where Types.ServiceIsAssignableFromImplementation(serviceType, type)
                let ctor = this.SelectImplementationTypeConstructorOrNull(type)
                           where ctor == null || options.IncludeDecorators || !Types.IsDecorator(serviceType, ctor)
                           where ctor == null || options.IncludeComposites || !Types.IsComposite(serviceType, ctor)
                           select type;

            return(types.ToArray());
        }