Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to disable assembly scanning when type missing from registry #343

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Option to disable assembly scanning when type missing from registry #343

wants to merge 1 commit into from

Conversation

bounav
Copy link

@bounav bounav commented Feb 3, 2017

Follow up on discussion #103.

Proposed change: to have an option to disable the default behaviour that scans assemblies for ICompositionRoot implementation when a type is missing from the service registry.

Having the option ScanAssembliesWhenRegistrationNotFound set to true by default doesn't change the current behaviour.

@@ -298,6 +298,32 @@ public void Register_AssemblyWithFunc_CallsAssemblyScanner()
}

[Fact]
public void Register_Assembly_CallsAssemblyScannerWhenAssemblyScanningEnabled()
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with the convention used to name the unit tests in this project so I will welcome suggestions if you can think of a better name ;)

@bounav
Copy link
Author

bounav commented Feb 6, 2017

Mmm appveyor is complaining that the code coverage is too low :(

@seesharper
Copy link
Owner

seesharper commented Feb 6, 2017 via email

@bounav
Copy link
Author

bounav commented Jan 26, 2018

Hello,

Is this pull request still relevant?

It looks like Lightinject now has a slightly different signature on IAssemblyScanner:

void Scan(Assembly assembly, IServiceRegistry serviceRegistry, Func<ILifetime> lifetime, Func<Type, Type, bool> shouldRegister, Func<Type, Type, string> serviceNameProvider);

Maybe the shouldRegister parameter could be used to disable the assembly scanning?

What about the service name provider? Could this extensibility point be used to disable assembly scanning?

Thanks!

@bounav
Copy link
Author

bounav commented Apr 5, 2022

It's been a while since there has been activity in this conversation thread...

That said, I think would still be useful to have an option to control the behaviour of LightInject when it comes to looking for ICompositionRoot implementations.

Out of the box, the CompositionRootTypeExtractor looks for assembly attributes to avoid having to go through all the types in the assembly... and falls back to doing the later when there are no such attributes.
This kicks in when one tries to get an instance of a type that isn't registered. Which means a slowdown in your program.

This behaviour is great IMHO when you get started and or are dealing with a small project.
What if however, you are dealing with a bigger project in which you have a lot of ICompositionRoot implementations and you'd rather register all the types manually and not have this auto scan behaviour?

With this in mind, and having had a look at the LightInject source a little bit, I ended up:

Creating a new ITypeExtractor that controls when an assembly should be processed or not. In that case it's as simple as if the assembly name starts with excludePattern do not process it.

public class ExcludingCompositionRootTypeExtractor : ITypeExtractor
{
    private readonly string excludePattern;
    private readonly ITypeExtractor compositionRootTypeExtractor;

   /// <param name="compositionRootTypeExtractor"></param>
   /// <param name="excludePattern">If that pattern is found in the filename, it is ignored.</param>
   public ExcludingCompositionRootTypeExtractor(string excludePattern, ITypeExtractor compositionRootTypeExtractor)
   {
        this.excludePattern = excludePattern;
        this.compositionRootTypeExtractor = compositionRootTypeExtractor;
    }

    public Type[] Execute(Assembly assembly)
    {
        // If the assembly matches the pattern don't try to extract composition roots
        if (assembly.FullName.IndexOf(excludePattern, StringComparison.Ordinal) >= 0)
        {
            return Type.EmptyTypes;
        }
            
        return compositionRootTypeExtractor.Execute(assembly);
    }
}

Then I defined an extension method that can be called immediately after creating the container to place my ExcludingCompositionRootTypeExtractor in between the CachedTypeExtrator and the CompositionRootTypeExtractor as well as inside the AssemblyScanner.

public static IServiceContainer HackCompositionRootTypeExtractorPipeline(this ServiceContainer serviceContainer)
{
    var concreteTypeExtractor = new CachedTypeExtractor(new ConcreteTypeExtractor());
            
    var compositionRootTypeExtractor = new CachedTypeExtractor(new ExcludingCompositionRootTypeExtractor("Watchdog.Relational", new CompositionRootTypeExtractor(new CompositionRootAttributeExtractor())));

    serviceContainer.CompositionRootTypeExtractor = compositionRootTypeExtractor;
            
    serviceContainer.AssemblyScanner = new AssemblyScanner(concreteTypeExtractor,
                serviceContainer.CompositionRootTypeExtractor,
                serviceContainer.CompositionRootExecutor,
                serviceContainer.GenericArgumentMapper);

    return serviceContainer;
}

And where the container is created you can call the hack method to change the composition root type extractor's behaviour:

var container = new ServiceContainer(containerOptions).HackCompositionRootTypeExtractorPipeline();
            

@seesharper Would you be interested in seeing a pull request where a callback can be defined on the container options and when that callback exists an extra CompositionRootTypeExtractor is added to the pipeline?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants