Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Ninject in a plugin like architecture

I'm learning DI, and made my first project recently.

In this project I've implement the repository pattern. I have the interfaces and the concrete implementations. I wonder if is possible to build the implementation of my interfaces as "plugins", dlls that my program will load dynamically.

So the program could be improved over time without having to rebuild it, you just place the dll on the "plugins" folder, change settings and voilá!

Is this possible? Can Ninject help with this?

like image 863
user32415 Avatar asked Dec 01 '08 13:12

user32415


2 Answers

While Sean Chambers' solution works in the case that you control the plugins, it does not work in the case where plugins might be developed by third parties and you don't want them to have to be dependent on writing ninject modules.

This is pretty easy to do with the Conventions Extension for Ninject:

public static IKernel CreateKernel() {     var kernel = new StandardKernel();      kernel.Scan(scanner => {         scanner.FromAssembliesInPath(@"Path\To\Plugins");         scanner.AutoLoadModules();         scanner.WhereTypeInheritsFrom<IPlugin>();         scanner.BindWith<PluginBindingGenerator<IPlugin>>();     });      return kernel; }  private class PluginBindingGenerator<TPluginInterface> : IBindingGenerator {     private readonly Type pluginInterfaceType = typeof (TPluginInterface);      public void Process(Type type, Func<IContext, object> scopeCallback, IKernel kernel)     {         if(!pluginInterfaceType.IsAssignableFrom(type))             return;         if (type.IsAbstract || type.IsInterface)             return;         kernel.Bind(pluginInterfaceType).To(type);     } } 

You can then get all loaded plugins with kernel.GetAll<IPlugin>().

The advantages of this method are:

  1. Your plugin dlls don't need to know that they are being loaded with ninject
  2. The concrete plugin instances will be resolved by ninject, so they can have constructors to inject types the plugin host knows how to construct.
like image 176
ungood Avatar answered Sep 26 '22 03:09

ungood


This question applies to the same answer I provided over here: Can NInject load modules/assemblies on demand?

I'm pretty sure this is what you're looking for:

var kernel = new StandardKernel(); kernel.Load( Assembly.Load("yourpath_to_assembly.dll"); 

If you look at KernelBase with reflector in Ninject.dll you will see that this call will recursively load all modules in the loaded assemblies (Load method takes an IEnumerable)

public void Load(IEnumerable<Assembly> assemblies) {     foreach (Assembly assembly in assemblies)     {         this.Load(assembly.GetNinjectModules());     } } 

I'm using this for scenarios where I don't want a direct assembly reference to something that will change very frequently and I can swap out the assembly to provide a different model to the application (granted I have the proper tests in place)

like image 45
Sean Chambers Avatar answered Sep 26 '22 03:09

Sean Chambers