Search code examples
c#dependency-injection.net-coreunity-container

System.InvalidOperationException: The current type, Microsoft.Extensions.Configuration.IConfiguration, is an interface and cannot be constructed


System.InvalidOperationException: The current type, Microsoft.Extensions.Configuration.IConfiguration, is an interface and cannot be constructed. Are you missing a type mapping?

I am using unity with .NET Core, and the error above is being given at this line:

container.RegisterInstance<IServiceA>(IoC.Resolve<IServiceB>());

IServiceB is registered as such:

container.RegisterType<IServiceB, ServiceA>(new ContainerControlledLifetimeManager());

I have a class ServiceA that implements IService B as follows.

public class ServiceA : IServiceB
{
   private IConfiguration _configuration;

   public ServiceA(IConfiguration configuration): base(configReader)
   {
        _configuration = configuration;
   }

   public string someVariable => _configuration.GetSection("Section").GetSection("WantedKey").Value;
    ...
}

I am using Microsoft.Extensions.Configuration.IConfiguration for the Configuration.

So I do not know how to map it because I am getting it from Microsoft.Extensions.Configuration.IConfiguration.

What am I doing wrong? How can I solve it?


Solution

  • Assuming a file like config.json

    {
      "Section" : {
        "WantedKey" : "WantedValue"
      }
    }
    

    You would first need to build a configuration instance

    IConfiguration config = new ConfigurationBuilder()
        .AddEnvironmentVariables()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("config.json", optional: true, reloadOnChange: true);
        .Build();
    

    And register that with the container

    container.RegisterInstance<IConfiguration>(config);
    

    In order for IConfiguration to be available to be resolved.

    Now ideally you really shouldn't be passing IConfiguration around for injection. It is usually accessed at the composition root to get settings for other dependencies. Try to avoid coupling to external framework dependencies.

    In this case you would want to create a strong type to hold the desired settings

    public class MySetting {
        public string WantedKey { get; set; }
    }
    

    And populate an instance of it from configuration

    MySetting setting = config.GetSection("Section").Get<MySetting>();
    

    You would register that with the container

    container.RegisterInstance<MySetting>(setting);
    

    and have that injected into dependents

    public class ServiceA : IServiceB {
        private readonly MySetting setting;
    
        public ServiceA(MySetting setting) {
            this.setting = setting;
        }
    
        public string someVariable => setting.WantedKey;
        //...
    }
    

    Reference Configuration in ASP.NET Core