6

I have some configuration interfaces

public interface IAppConfig
{
    IFeatureConfiguration FeatureConfiguration { get; set; }
    IOtherConfiguration OtherConfiguration { get; set; }
}
public interface IFeatureConfiguration 
{
    string SettingFoo { get; set; }
}
public interface IOtherConfiguration 
{
    string SettingBar { get; set; }
}

and classes

public class AppConfig : IAppConfig
{
    public IFeatureConfiguration FeatureConfiguration { get; set; }
    public IOtherConfiguration OtherConfiguration { get; set; }
}
public class FeatureConfiguration : IFeatureConfiguration 
{
    public string SettingFoo { get; set; }
}
public class OtherConfiguration : IOtherConfiguration 
{
    public string SettingBar { get; set; }
}

I wanted to bind appsetting.json to class in Startup.cs using code:

var appConfiguration = Configuration.GetSection("Configuration").Get<AppConfig>();

And I have exception: "Cannot create instance of type '[...].IFeatureConfiguration' because it is either abstract or an interface."

I know I can get rid of interfaces and use only classes, but I really want them... Any help would be appreciated

17
  • The message is clear. The configuration classes can't guess what type of object to create when all they have is an interface. Why are you using interfaces instead of classes? Commented Aug 27, 2020 at 14:16
  • Get inspects the type you passed as a type parameter, creates a new instance and sets its properties based on the config value paths. For complex properties, Get will try to do the same - use the property's type to create a new instance and fill it's properties with the matching subsection's values. When a property is an interface - which class should it instantiate? There may be an infinite number of classes that implement this specific interface Commented Aug 27, 2020 at 14:20
  • Are you trying to use those classes for different roles perhaps? Are you expecting IAppConfig to use one set of classes in one part of the application and a different set in another? Or pull data from different sources based on configuration - which is what the configuration subsystem already does? Both cases would be problematic Commented Aug 27, 2020 at 14:23
  • I inject IAppConfig to class from class library project. Two projects references this class library project - asp.net core api and full framework console app. So I wanted asp.net core api to bind this from appsetting.json and console app to implement config classes with some custom logic. And also interfaces will be more friendly to mock in UT. Commented Aug 28, 2020 at 7:26
  • I understand why I get this error. I asked question in hope that someone did something similar and found other way to do this. Commented Aug 28, 2020 at 7:29

1 Answer 1

0

I have a same scenario and I did it this way:

For example the appsettings.json is like as below:

{
  "Configuration": {
    "FeatureConfiguration ": {
      "SettingFoo": "Test setting foo"
    },
    "OtherConfiguration": {
      "SettingBar": "Test setting bar"
    }
  }
}

And you have some interfaces like as below:

public interface IAppConfig
{
    IFeatureConfiguration FeatureConfiguration { get; set; }
    IOtherConfiguration OtherConfiguration { get; set; }
}

public interface IFeatureConfiguration 
{
    string SettingFoo { get; set; }
}

public interface IOtherConfiguration 
{
    string SettingBar { get; set; }
}

And you implemented these interfaces like as below:

public class AppConfig : IAppConfig
{
    public IFeatureConfiguration FeatureConfiguration { get; set; }
    public IOtherConfiguration OtherConfiguration { get; set; }
}

public class FeatureConfiguration : IFeatureConfiguration 
{
    public string SettingFoo { get; set; }
}

public class OtherConfiguration : IOtherConfiguration 
{
    public string SettingBar { get; set; }
}

Firs, you must initalize the appConfiguration with concrete class objects

IAppConfig appConfiguration = new AppConfig {
   FeatureConfiguration = new FeatureConfiguration(),
   OtherConfiguration = new OtherConfiguration()
}

And you can bind nested configuration to this object. You can use Bind method for this purpose like as below:

Configuration.GetSection("Configuration").Bind(appConfiguration);

In conclusion appsettings.json bind to appConfiguration object.

You can see also this answer: https://stackoverflow.com/a/63170497/8810311

Sign up to request clarification or add additional context in comments.

15 Comments

That's not what that answer talks about. What's the point of adding interfaces to data-only settings classes? There's nothing to abstract. Bind works fine without the interfaces.
@PanagiotisKanavos this is for loose coupling.
You already have that through DI and Invertion of Control, not interfaces. You can already create your classes without having to bring up the entire DI and configuration middleware, just by passing an instance of the classes
Yes, and so is the answer you linked to, the official documentation and all .NET Core code is sure. People don't use interfaces for settings DTOs. There's no such thing as non-initialized object. Once constructed, the object is initialized. Changing the original values isn't initialization. Interfaces have nothing to do with how Bind<>, Get<> or Configure<> work
Perhaps you should check Configuration, Custom Configuration Providers and the Options pattern. This question isn't asking about a configuration service but why the Configuration middleware hates interfaces. Because it's not meant to produce interfaces
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.