LightInject
LightInject copied to clipboard
Option to disable assembly scanning when type missing from registry
Follow up on discussion https://github.com/seesharper/LightInject/issues/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.
Mmm appveyor is complaining that the code coverage is too low :(
That is not your fault. It is caused by code being added prior to your PR. I will review your PR ASAP :)
On Mon, Feb 6, 2017 at 10:57 AM, Benjamin [email protected] wrote:
Mmm appveyor is complaining that the code coverage is too low :(
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/seesharper/LightInject/pull/343#issuecomment-277635481, or mute the thread https://github.com/notifications/unsubscribe-auth/AA_HWbKufdVwyIyFmv8SlcBnNU6cPoXhks5rZu6PgaJpZM4L2fcP .
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!
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?