Skip to content

Commit

Permalink
Use sets internally to avoid duplicate types and assemblies
Browse files Browse the repository at this point in the history
  • Loading branch information
khellang committed Sep 1, 2023
1 parent a201d42 commit 33f606d
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 29 deletions.
4 changes: 2 additions & 2 deletions src/Scrutor/AttributeSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ namespace Scrutor;

internal class AttributeSelector : ISelector
{
public AttributeSelector(IEnumerable<Type> types)
public AttributeSelector(ISet<Type> types)
{
Types = types;
}

private IEnumerable<Type> Types { get; }
private ISet<Type> Types { get; }

void ISelector.Populate(IServiceCollection services, RegistrationStrategy? registrationStrategy)
{
Expand Down
20 changes: 20 additions & 0 deletions src/Scrutor/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#if !NET8_0_OR_GREATER

using System.Collections.Generic;

namespace Scrutor;

internal static class EnumerableExtensions
{
public static ISet<T> ToHashSet<T>(this IEnumerable<T> source)
{
if (source is ISet<T> set)
{
return set;
}

return new HashSet<T>(source);
}
}

#endif
6 changes: 3 additions & 3 deletions src/Scrutor/ImplementationTypeFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ namespace Scrutor;

internal class ImplementationTypeFilter : IImplementationTypeFilter
{
public ImplementationTypeFilter(IEnumerable<Type> types)
public ImplementationTypeFilter(ISet<Type> types)
{
Types = types;
}

internal IEnumerable<Type> Types { get; private set; }
internal ISet<Type> Types { get; private set; }

public IImplementationTypeFilter AssignableTo<T>()
{
Expand Down Expand Up @@ -151,7 +151,7 @@ public IImplementationTypeFilter Where(Func<Type, bool> predicate)
{
Preconditions.NotNull(predicate, nameof(predicate));

Types = Types.Where(predicate);
Types.IntersectWith(Types.Where(predicate));
return this;
}
}
10 changes: 5 additions & 5 deletions src/Scrutor/ImplementationTypeSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ namespace Scrutor;

internal class ImplementationTypeSelector : IImplementationTypeSelector, ISelector
{
public ImplementationTypeSelector(ITypeSourceSelector inner, IEnumerable<Type> types)
public ImplementationTypeSelector(ITypeSourceSelector inner, ISet<Type> types)
{
Inner = inner;
Types = types;
}

private ITypeSourceSelector Inner { get; }

private IEnumerable<Type> Types { get; }
private ISet<Type> Types { get; }

private List<ISelector> Selectors { get; } = new();

Expand Down Expand Up @@ -135,15 +135,15 @@ void ISelector.Populate(IServiceCollection services, RegistrationStrategy? regis

private IServiceTypeSelector AddSelector(IEnumerable<Type> types)
{
var selector = new ServiceTypeSelector(this, types);
var selector = new ServiceTypeSelector(this, types.ToHashSet());

Selectors.Add(selector);

return selector;
}

private IEnumerable<Type> GetNonAbstractClasses(bool publicOnly)
private ISet<Type> GetNonAbstractClasses(bool publicOnly)
{
return Types.Where(t => t.IsNonAbstractClass(publicOnly));
return Types.Where(t => t.IsNonAbstractClass(publicOnly)).ToHashSet();
}
}
4 changes: 2 additions & 2 deletions src/Scrutor/ReflectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ public static IEnumerable<Type> FindMatchingInterface(this Type type, Action<Typ

var matchedInterfaces = GetImplementedInterfacesToMap(type)
.Where(x => string.Equals(x.Name, matchingInterfaceName, StringComparison.Ordinal))
.ToArray();
.ToHashSet();

if (matchedInterfaces.Length == 0)
if (matchedInterfaces.Count == 0)
{
yield break;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Scrutor/ServiceTypeSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ namespace Scrutor;

internal class ServiceTypeSelector : IServiceTypeSelector, ISelector
{
public ServiceTypeSelector(IImplementationTypeSelector inner, IEnumerable<Type> types)
public ServiceTypeSelector(IImplementationTypeSelector inner, ISet<Type> types)
{
Inner = inner;
Types = types;
}

private IImplementationTypeSelector Inner { get; }

private IEnumerable<Type> Types { get; }
private ISet<Type> Types { get; }

private List<ISelector> Selectors { get; } = new();

Expand Down
29 changes: 14 additions & 15 deletions src/Scrutor/TypeSourceSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ public IImplementationTypeSelector FromDependencyContext(DependencyContext conte
Preconditions.NotNull(predicate, nameof(predicate));

var assemblyNames = context.RuntimeLibraries
.SelectMany(library => library.GetDefaultAssemblyNames(context));
.SelectMany(library => library.GetDefaultAssemblyNames(context))
.ToHashSet();

Check warning on line 75 in src/Scrutor/TypeSourceSelector.cs

View check run for this annotation

Codecov / codecov/patch

src/Scrutor/TypeSourceSelector.cs#L74-L75

Added lines #L74 - L75 were not covered by tests

var assemblies = LoadAssemblies(assemblyNames);

Expand All @@ -82,19 +83,21 @@ public IImplementationTypeSelector FromAssemblyDependencies(Assembly assembly)
{
Preconditions.NotNull(assembly, nameof(assembly));

var assemblies = new List<Assembly> { assembly };

try
{
var dependencyNames = assembly.GetReferencedAssemblies();
var dependencyNames = assembly
.GetReferencedAssemblies()
.ToHashSet();

Check warning on line 90 in src/Scrutor/TypeSourceSelector.cs

View check run for this annotation

Codecov / codecov/patch

src/Scrutor/TypeSourceSelector.cs#L88-L90

Added lines #L88 - L90 were not covered by tests

var assemblies = LoadAssemblies(dependencyNames);

Check warning on line 92 in src/Scrutor/TypeSourceSelector.cs

View check run for this annotation

Codecov / codecov/patch

src/Scrutor/TypeSourceSelector.cs#L92

Added line #L92 was not covered by tests

assemblies.AddRange(LoadAssemblies(dependencyNames));
assemblies.Add(assembly);

Check warning on line 94 in src/Scrutor/TypeSourceSelector.cs

View check run for this annotation

Codecov / codecov/patch

src/Scrutor/TypeSourceSelector.cs#L94

Added line #L94 was not covered by tests

return InternalFromAssemblies(assemblies);
}
catch
{
return InternalFromAssemblies(assemblies);
return FromAssemblies(assembly);

Check warning on line 100 in src/Scrutor/TypeSourceSelector.cs

View check run for this annotation

Codecov / codecov/patch

src/Scrutor/TypeSourceSelector.cs#L100

Added line #L100 was not covered by tests
}
}

Expand Down Expand Up @@ -132,11 +135,7 @@ public IServiceTypeSelector FromTypes(IEnumerable<Type> types)
{
Preconditions.NotNull(types, nameof(types));

var selector = new ImplementationTypeSelector(this, types);

Selectors.Add(selector);

return selector.AddClasses();
return AddSelector(types).AddClasses();
}

public void Populate(IServiceCollection services, RegistrationStrategy? registrationStrategy)
Expand All @@ -154,12 +153,12 @@ private IImplementationTypeSelector InternalFromAssembliesOf(IEnumerable<Type> t

private IImplementationTypeSelector InternalFromAssemblies(IEnumerable<Assembly> assemblies)
{
return AddSelector(assemblies.SelectMany(asm => asm.DefinedTypes).Select(x => x.AsType()));
return AddSelector(assemblies.SelectMany(asm => asm.GetTypes()));
}

private static IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyName> assemblyNames)
private static ISet<Assembly> LoadAssemblies(ISet<AssemblyName> assemblyNames)
{
var assemblies = new List<Assembly>();
var assemblies = new HashSet<Assembly>();

Check warning on line 161 in src/Scrutor/TypeSourceSelector.cs

View check run for this annotation

Codecov / codecov/patch

src/Scrutor/TypeSourceSelector.cs#L161

Added line #L161 was not covered by tests

foreach (var assemblyName in assemblyNames)
{
Expand All @@ -179,7 +178,7 @@ private static IEnumerable<Assembly> LoadAssemblies(IEnumerable<AssemblyName> as

private IImplementationTypeSelector AddSelector(IEnumerable<Type> types)
{
var selector = new ImplementationTypeSelector(this, types);
var selector = new ImplementationTypeSelector(this, types.ToHashSet());

Selectors.Add(selector);

Expand Down

0 comments on commit 33f606d

Please sign in to comment.