Ninject bind all classes implementing the same interface

10,583

Solution 1

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());

Solution 2

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)
   {
      ...
   }
}
Share:
10,583

Related videos on Youtube

Catalin
Author by

Catalin

Hello, My name is Catalin and I am a full-stack developer with the primary focus on .NET. Some of the technologies I like to work with include: ASP.NET Core, AWS, Azure, MongoDB, JavaScript, RequireJS, Gulp, React, RabbitMQ, AWS SAM I like challenges, I am a strong advocate of constant refactoring and I try to avoid coding compromises as much as possible. On my spare time I like to work on my personal project, https://github.com/KissLog-net/KissLog.Sdk Some of my favorite (professional) books are: Adaptive Code via C#: Agile coding with design patterns and SOLID principles Learning JavaScript Design Patterns Pragmatic Programmer

Updated on September 16, 2022

Comments

  • Catalin
    Catalin almost 2 years

    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();
    });
    
  • Catalin
    Catalin over 11 years
    The last binding won't overwrite the previous ones?
  • Andrew Savinykh
    Andrew Savinykh over 11 years
    @MikroDel: so in your example, which class will be injected when there is a need for IStartUpTask interface? This looks wrong.
  • MikroDel
    MikroDel over 11 years
    @RaraituL I have updated my answer to make it easier to understand
  • Andrew Savinykh
    Andrew Savinykh over 11 years
    @MikroDel: that's not what he asked.
  • Catalin
    Catalin over 11 years
    @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 need
  • MikroDel
    MikroDel over 11 years
    @RaraituL - it was my try to help you )
  • MikroDel
    MikroDel over 11 years
    @RaraituL - and your qeustion "The last binding won't overwrite the previous ones?" - no you can use all the bindings
  • FNMT8L9IN82
    FNMT8L9IN82 almost 11 years
    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!
  • Umar Farooq Khawaja
    Umar Farooq Khawaja almost 8 years
    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.
  • mivra
    mivra over 7 years
    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.
  • Simone
    Simone over 4 years
    Same as @noocyte.