Search code examples
c#dependency-injectionninject

c# ninject inject dependency in a instantiated class


I have a C# MVC project using Repository Pattern and Ninject (DI). All is working fine.

Inside a Repository Im instantiating a class to process some calls to external APIs like this:

public class EmployeeRepository : IEmployeeRepository
    {
        private readonly AppState _appState;

        public EmployeeRepository(IAppStateProvider appStateProvider)
        {
            _appState = appStateProvider.AppState;
        }

        public bool ProcessEmployee(long employeeId, object data)
        {
            var api = new ExternalAPI(_appState);
            api.PostData(data);
            return true;
        }
}

Then my ExternalAPI.cs class is:

public class ExternalAPI: BaseRepository
    {
        [Inject]
        public ILogRepository Logger { get; set; }

        private readonly AppState _appState;

        public ExternalAPI(AppState appState)
        {
            _appState = appState;
        }


        private bool PostData(object data)
        {
            bool returnVal = true;

            // Some code here....

            Logger.InsertLog(data); // HERE Logger IS NULL

            return returnVal;
        }
 }

I get an exception here because Logger is null.

And in my main project NinjectWebCommon.cs file Im registering the dependency correctly:

private static void RegisterServices(IKernel kernel)
        {

            kernel.Bind(typeof(ILogRepository)).To(typeof(Data.LogRepository));
         }

Any clue why the [Inject] of ILogRepository is not working in the ExternalAPI class?

Maybe because from EmployeeRepository Im creating a new instance of that class:

var api = new ExternalAPI(_appState);

Any advice and how can I make the injection of ILogRepository work in ExternalAPI class?


Solution

  • Reference Explicit Dependencies Principle

    Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.

    ExternalAPI is dependent on ILogRepository and AppState so that is what should be injected into it

    public class ExternalAPI: BaseRepository, IExternalAPI {
    
        private readonly ILogRepository logger;
        private readonly AppState _appState;
    
        public ExternalAPI(IAppStateProvider appStateProvidere, ILogRepository logger) {
            _appState = appStateProvidere.AppState;
            this.logger = logger;
        }
    
    
        public bool PostData(object data) {
            bool returnVal = true;
    
            // Some code here....
    
            logger.InsertLog(data); // HERE Logger IS NULL
    
            return returnVal;
        }
    }
    

    EmployeeRepository is dependent on ExternalAPI so that is what should be injected into it.

    public class EmployeeRepository : IEmployeeRepository {
        private readonly IExternalAPI api;
    
        public EmployeeRepository(IExternalAPI api) {
            this.api = api;
        }
    
        public bool ProcessEmployee(long employeeId, object data) {
            api.PostData(data);
            return true;
        }
    }
    

    Ensure that any necessary dependencies are registered with the container

    private static void RegisterServices(IKernel kernel) {
        //...
        kernel.Bind(typeof(ILogRepository)).To(typeof(Data.LogRepository));
        kernel.Bind(typeof(IExternalAPI)).To(typeof(ExternalAPI));
        //...
     }