Ninject -> Scan assemblies for matching interfaces and load as modules
Asked Answered
S

2

6

In earlier versions of Ninject.Extensions.Conventions, it was pretty easy to scan a directory for assemblies, filter classes by interface and then load all containing ninject modules.

kernel.Scan(scanner =>
    scanner.FromAssembliesInPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
    scanner.AutoLoadModules();
    scanner.WhereTypeInheritsFrom<IPlugin>());

public class MyPlugin : NinjectModule, IPlugin {

     public override void Load() {
          Bind<IRepositoryFromPluginHost>().To<MyPluginImpl>().Named("special");
     }
}

However, after I updated lately to the newest release, everything seems gone and I'm unable to

  1. Auto load modules
  2. Filter types by interfaces

Does anybody have a solution for this?

Shipment answered 13/5, 2014 at 10:5 Comment(0)
B
4

There's still the https://github.com/ninject/ninject.extensions.conventions extension. However, the interface has changed, to something along the lines of:

kernel.Bind(x =>
{
    x.FromAssembliesInPath("somepath")
     .IncludingNonePublicTypes()
     .SelectAllClasses()
     .InheritedFrom<IPlugin>()
     .BindDefaultInterface() // Binds the default interface to them;
});

Update: How about you bind all IPlugin to IPlugin using the conventions extension (as above), and then do:

var plugins = IResolutionRoot.GetAll<IPlugin>();
kernel.Load(plugins);
Boehmite answered 13/5, 2014 at 10:43 Comment(10)
Yes, but that is not exactly what I intended. Your example loads all classes from assemblies in a certain path that inherit from a certain interface and binds the default interface. However, what I want to do is just loading Ninject modules as plugins from assemblies where the binding instructions are inside them.Shipment
Sorry that i got it wrong. I'll look into whether there is some way to achieve that. Ninject StandardKernel by default still auto-loads all ´IModule´ in assemblies beginning with ´Ninject.Extensions.´, so the code may be accessible.Boehmite
Sorry it took me so long. I've updated the answer to show how we used to handle plugins. If you don't want the extra IPlugin bindings floating around, i would go with @Eric's answer.Boehmite
In v3.2.0.0 of ninject.extensions.conventions, that should read "IncludingNonePublicTypes()" rather than "IncludeNonPublicTypes()"Arietta
@Xaniff: yes, it does. While grammatically incorrect, I've quoted the code correctly. There's nothing to edit for me here.Boehmite
@Boehmite Well, grammar aside, I'm telling you that I just typed your code into VS (as I was looking for a similar answer) and "IncludeNonePublicTypes" isn't an option for me. i.imgur.com/7G4T9Nq.jpgArietta
@Xaniff: i think your screenshot contradicts what your saying. It actually shows IncludingNonePublicTypes with None and not Non! And that's the same that my code above shows...Boehmite
@Xaniff however you're welcome to suggest an edit to the post so i can review it ;-)Boehmite
@Boehmite In my original edit, I mistyped the intended method name. Specifically, I was looking at "Include" -> "Including".Arietta
@Xaniff Oh alright. I thought it was about None vs Non. Thanks for the edit, I've approved it.Boehmite
I
1

Maybe the hard way, but something like this will get you a list of types that are derived from NinjectModule.

var assemblies = AppDomain.CurrentDomain.GetAssemblies(); 
List<Type> types = new List<Type>();
foreach (var assembly in assemblies) 
{
    types.AddRange(GetModules(assembly)); 
}


    IEnumerable<Type> GetModules(Assembly assembly)
    {
         assembly.GetTypes()
              .Where(t => t.BaseType == typeof(NinjectModule));       
    }

To load your module try this.

(Activator.CreateInstance(type) as NinjectModule).Load();

Imperturbable answered 17/5, 2014 at 2:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.