Ninject bind all classes implementing the same interface
Asked Answered
D

2

14

I have an interface class:

public interface IStartUpTask
{
    bool IsEnabled { get; }
    void Configure();
}

I have multimple classes implementing the same interface

One of the classes looks like this:

public class Log4NetStartUpTask : IStartUpTask
{
    public bool IsEnabled { get { return true; } }

    public void Configure()
    {
        string log4netConfigFilePath = ConfigurationManager.AppSettings["log4netConfigFilePath"];
        if (log4netConfigFilePath == null)
            throw new Exception("log4netConfigFilePath configuration is missing");

        if (File.Exists(log4netConfigFilePath) == false)
            throw new Exception("Log4Net configuration file was not found");

        log4net.Config.XmlConfigurator.Configure(
            new System.IO.FileInfo(log4netConfigFilePath));
    }
}

How can i tell Ninject that i want all the classes implementing the IStartUpTask to bind to themself automatically?

I found an example using StructureMap which does this, but i don't know how to do it in Ninject.

Scan(x => {
    x.AssemblyContainingType<IStartUpTask>();
    x.AddAllTypesOf<IStartUpTask>();
    x.WithDefaultConventions();
});
Dropsy answered 8/3, 2013 at 9:10 Comment(0)
S
14

How can i tell Ninject that i want all the classes implementing the IStartUpTask to bind to themself automatically?

First of all, let me tell you that Ninject binds all classes to themselves automatically. You do not need to do anything special for that.

Having said that, I understand that you might want the explicit binding if you want to change scope or attach names or metadata. In this case read-on.

I do not know if it is possible to do what you are after in vanilla ninject, but you can use ninject.extensions.conventions. Using this library you can write:

Kernel.Bind(x => 
    x.FromThisAssembly()
    .SelectAllClasses()
    .InheritedFrom<IStartUpTask>()
    .BindToSelf());
Suiting answered 8/3, 2013 at 9:58 Comment(3)
This sort of worked for me, but I had to do 'BindSingleInterface' and not BindToSelf. But no matter, the trick for me was the 'InheritedFrom' bits. Thanx!Blondellblondelle
I found this solution, but it somehow "did not work" for me. It took me a while to find out why, so I'm adding it here to add more context. By default Ninject binds only public classes, you have to call IncludingNonePublicTypes() method if you want to bind internal classes.Exegetics
Same as @noocyte.Seagoing
I
3

you can call it explicit in your code:

...
Bind<IStartUpTask>().To<Log4NetStartUpTask>();
Bind<IStartUpTask>().To<SomeOtherStartUpTask>();
...

Use it in SomeClass

public class SomeClass
{
   private readonly List<IStartUpTask> startUpTaskList;

   public SomeClass(IEnumerable<IStartUpTask> startUpTaskList)
   {
      this.startUpTaskList = startUpTaskList;
   }

   foreach (var startUpTask in this.startUpTaskList)
   {
      ...
   }
}
Irrationality answered 8/3, 2013 at 9:13 Comment(8)
The last binding won't overwrite the previous ones?Dropsy
@MikroDel: so in your example, which class will be injected when there is a need for IStartUpTask interface? This looks wrong.Suiting
@RaraituL I have updated my answer to make it easier to understandIrrationality
@MikroDel: that's not what he asked.Suiting
@MikroDel: yes, this is getting complicated. I know you can name the bindings like kernel.Bind<IStartUpTask>().To<Log4NetStartUpTask>().Named("log4Net"); but it adds extra functionality i don't needDropsy
@RaraituL - it was my try to help you )Irrationality
@RaraituL - and your qeustion "The last binding won't overwrite the previous ones?" - no you can use all the bindingsIrrationality
The key point here is that if there are multiple bindings to the same type (in this case Log4NetStartupTask and SomeOtherStartupTask are being bound to IStartupTask), then you either have to provide additional conditions to find the one unique implementation of IStartupTask to be injected, or inject all implementations as an IEnumerable<IStartupTask>. Bindings don't overwrite each other.Maxwellmaxy

© 2022 - 2024 — McMap. All rights reserved.