0
votes

I have the following scenario for declaring export plugins for my application:

public abstract class PluginBase : NinjectModule
{
    protected PluginBase(IDataSource source)
    {
         // ...
    }

    public override void Load()
    {
         Bind<PluginBase>().To(GetType());
    }
}
public class RealPlugin : PluginBase
{
    public RealPlugin(IDataSource source)
    {
        // ...
    }
}

Unfortunatelly, Kernel.Load(AssemblyName) doesn't seem to detect RealPlugin as loadable element and the Load() method is never called. It works if I add an extra public constructor with no arguments to both classes. However, I actually don't want to do that because I don't want anyone to create an instance of RealPlugin without specifying the data source.

An ugly workaround seems to be to mark the parameterless constructors with [Obsolete], which at least prevents accidental usage of them.

Of course, I could also create separate classes deriving from NinjectModule to create the Bindings, but that requires another class for each of my Plugins, which is also not so nice (and prevents binding to the dynamic type of the instance, as seen above)

Anyone got an idea how such a plugin can be registered without having a public parameterless constructor?

1
I'm pretty sure ninject doesn't support injecting anything into Module constructors - so if a Module requires a ctor-parameter you'll always have to new it yourself and load it by Kernel.Load(NinjectModule) instead of using Kernel.Load(AssemblyName). - BatteryBackupUnit
@BatteryBackupUnit: I don't care injecting anything into the module, I just don't want to create a public constructor. I would be happy if it would work with protected or private constructors as well. - PMF

1 Answers

0
votes

In Reflection, by default, only "public" types are considered. Apparently ninject uses the default values. So you'll have to roll your own implementation which uses reflection to find all classes which match all of these criteria:

  • inheriting from NinjectModule (also indirectly)
  • not abstract
  • has a parameter-less constructor

then these need to be instanciated and passed on to Kernel.Load(NinjectModule).

You could, just as well, look at the source code of Kernel.Load(AssemblyName) and copy and modify it according to your needs. Most likely the code making use of reflection will just require a false switched to a true in one or two places - or using a different method overload which considers non-public members, too.