/// <summary> /// Find and register services from <see cref="IServiceRegistration"/> definitions found, optionally including those not loaded. /// </summary> /// <param name="services">The services collection.</param> /// <param name="startingPoint">Assemblies to start the search from, if not provided the entry assembly is used: Assembly.GetEntryAssembly().</param> /// <param name="includeNonPublic">True to include non-public types in the search, otherwise false to search only public types.</param> /// <param name="assemblySearchOptions">How to search for additional assemblies to include.</param> /// <param name="assemblyNamePrefixes">Case insensitive prefixes of assembly names and file names (*.dlls) to include in search, null/empty to include all.</param> public static IServiceCollection AddRegisteredServices(this IServiceCollection services, Assembly startingPoint = null, bool includeNonPublic = false, AssemblySearchOptions assemblySearchOptions = AssemblySearchOptions.Default, bool throwOnError = false, params string[] assemblyNamePrefixes) {
/// <summary> /// Find all defined types across all referenced assemblies including those in the execution paths. /// </summary> /// <param name="startingPoint">Assemblies to start the search from, if not provided the entry assembly is used: Assembly.GetEntryAssembly().</param> /// <param name="ofType">Type which the results must be assignable to, null for no filter.</param> /// <param name="typeFilter">Predicate to filter out returned types, or null for the default which is to include all public instance non-abstract and non-generic classes or value-types.</param> /// <param name="mustHavePublicDefaultCtor">True to ensure all returned types have a public default constructor defined, otherwise false.</param> /// <param name="assemblySearchOptions">How to search for additional assemblies to include.</param> /// <param name="throwOnError">True to throw on any assembly load errors, otherwise false.</param> /// <param name="assemblyNamePrefixes">Case insensitive prefixes of assembly names and file names (*.dlls) to include in search, null/empty to include all.</param> /// <returns></returns> public static IEnumerable <Type> FindAllTypes(Assembly startingPoint = null, Type ofType = null, Predicate <Type> typeFilter = null, bool mustHavePublicDefaultCtor = false, AssemblySearchOptions assemblySearchOptions = AssemblySearchOptions.Default, bool throwOnError = false, IEnumerable <string> assemblyNamePrefixes = null) { return(FindAssemblies(startingPoint, assemblySearchOptions, throwOnError, assemblyNamePrefixes) .SelectMany(a => a.GetLoadableTypes()) .Where(t => ofType == null || ofType.IsAssignableFrom(t)) .Where(t => typeFilter?.Invoke(t) ?? ((t.IsClass || t.IsValueType) && t.IsPublic && !t.IsAbstract && !t.IsGenericType)) .Where(t => !mustHavePublicDefaultCtor || t.IsValueType || t.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null) != null) .Distinct() // shouldn't be required .ToList()); }
public static IEnumerable <Assembly> FindAssemblies(Assembly startingPoint = null, AssemblySearchOptions assemblySearchOptions = AssemblySearchOptions.Default, bool throwOnError = false, IEnumerable <string> assemblyNamePrefixes = null) { var directorySearchOptions = assemblySearchOptions.HasFlagSet(AssemblySearchOptions.IncludeSubdirectories) ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; var matchedAssemblies = new List <Assembly>(); var assembliesSearched = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); var assembliesToSearch = new Queue <Assembly>(); startingPoint ??= Assembly.GetEntryAssembly(); assembliesToSearch.Enqueue(startingPoint); if (assemblySearchOptions.HasFlagSet(AssemblySearchOptions.StartingDirectory)) { assembliesToSearch.EnqueueRange(FindAssemblies(startingPoint, assemblyNamePrefixes, directorySearchOptions, assembliesSearched, throwOnError)); } while (assembliesToSearch.Count > 0) { var assembly = assembliesToSearch.Dequeue(); if (assembliesSearched.Add(assembly.FullName)) { if (!assemblyNamePrefixes.Any() || assemblyNamePrefixes.Any(n => assembly.FullName.StartsWith(n, StringComparison.InvariantCultureIgnoreCase))) { matchedAssemblies.Add(assembly); if (assemblySearchOptions.HasFlagSet(AssemblySearchOptions.ReferencedAssemblies)) { assembliesToSearch.EnqueueRange(assembly.GetReferencedAssemblies().Select(a => { try { return(Assembly.Load(a)); } catch { if (throwOnError) { throw; } return(null); } }).WhereNotNull()); } if (assembly != startingPoint && assemblySearchOptions.HasFlagSet(AssemblySearchOptions.AssemblyDirectories)) { assembliesToSearch.EnqueueRange(FindAssemblies(assembly, assemblyNamePrefixes, directorySearchOptions, assembliesSearched, throwOnError)); } } } } return(matchedAssemblies .Distinct() // shouldn't be required .ToList()); }
/// <summary> /// Find all defined types across all referenced assemblies including those in the execution paths. /// </summary> /// <param name="startingPoint">Assemblies to start the search from, if not provided the entry assembly is used: Assembly.GetEntryAssembly().</param> /// <param name="ofType">Type which the results must be assignable to, null for no filter.</param> /// <param name="typeFilter">Predicate to filter out returned types, or null for the default which is to include all public instance non-abstract and non-generic classes or value-types.</param> /// <param name="mustHavePublicDefaultCtor">True to ensure all returned types have a public default constructor defined, otherwise false.</param> /// <param name="assemblySearchOptions">How to search for additional assemblies to include.</param> /// <param name="throwOnError">True to throw on any assembly load errors, otherwise false.</param> /// <param name="assemblyNamePrefixes">Case insensitive prefixes of assembly names and file names (*.dlls) to include in search, null/empty to include all.</param> /// <returns></returns> public static IEnumerable <Type> FindAllTypes(Assembly startingPoint = null, Type ofType = null, Predicate <Type> typeFilter = null, bool mustHavePublicDefaultCtor = false, AssemblySearchOptions assemblySearchOptions = AssemblySearchOptions.Default, bool throwOnError = false, params string[] assemblyNamePrefixes) { return(FindAllTypes(startingPoint, ofType, typeFilter, mustHavePublicDefaultCtor, assemblySearchOptions, throwOnError, (IEnumerable <string>)assemblyNamePrefixes)); }