Search code examples
c#wpfdependency-injectionninject

Ninject Dependency Injection - Two Concrete classes


I am learning Ninject for dependency injection and have a use case where two classes implement the same interface in a WPF MVVM applicaiton. In my research the dependencies can be bound using contextual bindings, however I am unsure of how that would work in this scenario.

For example:

public interface IModifyContent {
    string ModifyOperation();
}

public class UpdateContent : IModifyContent {
    public string ModifyOperation() {
        return "This is the update operation";
    }
}

public class DeleteContent : IModifyContent {
    public string ModifyOperation() {
        return "This is the delete operation";
    }
}

public class ModifyFile {
    private IFileManager _fileManager;
    private IModifyContent _modifyContent;
    
    public ModifyFile(IFileManager fileManager, IModifyContent modifyContent) 
    {
        _fileManager = _fileManager;
        _modifyContent = modifyContent;
    }
    
    public void Modify() 
    {
        var fileContent = _fileManager.ReadFileContents(); // Returns file content
        
        var result = _modifyContent.ModifyOperation(); // ModifyOperation would actually modify content in some way...
        
        // Do stuff with result
    }
}

Then the binding would look something like this:

Bind<IModifyContent>().To<UpdateContent>();
Bind<IModifyContent>().To<DeleteContent>();
// Other bindings

In this my thinking is as follows:

  • ModifyFile class is used for common funcitonaility when modifying a file, whereas the two concrete implementations of IModifyContent define the unique behaviour that can occur for the different operations.
  • Depending on what calls/ invokes ModifyFile I want to pass in a different concrete implementation of IModifyContent. I.e When calling from update business logic or view model, then the concrete UpdateContent should be passed as the dependency to ModifyFile.

Firstly is this a good design approach to avoid repeating common logic and secondly how can I inject the correct concrete implementation depending on what class/ invokes ModifyFile?


Solution

  • There is a way through which you can achieve this !!!

    You can register dependencies with specific name.

    IKernel ninjectKernel = new StandardKernel();
    
    // Defining Bindings with specific names
    ninjectKernel.Bind<IModifyContent>().To<UpdateContent>().Named("Update");
    ninjectKernel.Bind<IModifyContent>().To<DeleteContent>().Named("Delete");
    

    You can resolved these dependencies at compile time as shown below:

    // Resolving dependencies using binding name
    IModifyContent updateContent = ninjectKernel.Get<IModifyContent>("Update");
    IModifyContent deleteContent = ninjectKernel.Get<IModifyContent>("Delete");
    

    Once resolve they can be use to execute their codes. Below is the sample code which refers to the implementation that you have provided.

    Console.WriteLine(updateContent.ModifyOperation());
    Console.WriteLine(deleteContent.ModifyOperation());
    
    // Output
    // This is the update operation
    // This is the delete operation
    

    You can resolve such dependencies at run time as well. For more information refer to the following link:

    https://github.com/ninject/Ninject/wiki/Contextual-Binding