简体   繁体   中英

How do I use ASP.NET Core App Settings with Simple Injector

I am new to ASP.NET Core and need some direction. I am trying to figure out a simple scenario with using app settings in ASP.NET Core while also using Simple Injector.

I first set up my Strongly-Type configuration settings as explained here by Rick Strahl. This works great.

  public class MySettings
  {
    public string ApplicationName { get; set; }
  }

appsetting.json

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "MySettings": {
    "ApplicationName": "Test Service"
  }
}

Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
      // Add framework services.
      services.AddMvc();

      // Add Options
      services.AddOptions();

      // Add our Config object so it can be injected
      services.Configure<MySettings>(Configuration.GetSection("MySettings"));
      services.AddSingleton(GetTestBroker(container));

      //Simple Injector       
      //services.AddSingleton<IControllerActivator>(new SimpleInjectorControllerActivator(container));
      //services.AddSingleton<IViewComponentActivator>(new SimpleInjectorViewComponentActivator(container));


  }

In our other projects were are using Simple Injector for DI. After adding the Simple Injector package and configuring it per the instructions I see that my IOptions configuration breaks.

What I'd like to know is what would be best practice for implementing a configuration in ASP.NET Core and using another DI library like Simple Injector together?

The ASP.NET Core integration guide for Simple Injector states the following:

ASP.NET Core contains a new configuration model based on an IOption<T> abstraction. We advise against injecting IOption<T> dependencies into your application components. Instead let components depend directly on configuration objects and register them as Singleton . This ensures that configuration values are read during application start up and allows to verify them at that point in time, allowing the application to fail-fast.

Letting application components depend on IOptions<T> has some unfortunate downsides. First of all, it causes application code to take an unnecessary dependency on a framework abstraction. This is a violation of the Dependency Injection Principle that prescribes the use of application-tailored abstractions. Injecting an IOptions<T> into an application component only makes this component more difficult to test, while providing no benefits. Application components should instead depend directly on the configuration values they require.

IOptions<T> configuration values are read lazily. Although the configuration file might be read upon application start up, the required configuration object is only created when IOptions<T>.Value is called for the first time. When deserialization fails, because of application misconfiguration, such error will only be appear after the call to IOptions<T>.Value . This can cause misconfigurations to keep undetected for much longer than required. By reading -and verifying- configuration values at application start up, this problem can be prevented. Configuration values can be injected as singletons into the component that requires them.

To make things worse, in case you forget to configure a particular section (by omitting a call to services.Configure<T> ) or when you make a typo while retrieving the configuration section (by supplying the wrong name to Configuration.GetSection(name) ), the configuration system will simply supply the application with a default and empty object instead of throwing an exception! This may make sense in some cases but it will easily lead to fragile applications.

Since you want to verify the configuration at start-up, it makes no sense to delay reading it, and that makes injecting IOption into your components plain wrong. Depending on IOptions<T> might still be useful when bootstrapping the application, but not as a dependency anywhere else.

Once you have a correctly read and verified configuration object, registration of the component that requires the configuration object is as simple as this:

 MyMailSettings mailSettings = config.GetSection("Root:SectionName").Get<MyMailSettings>(); // Verify mailSettings here (if required) container.Register<IMessageSender>(() => new MailMessageSender(mailSettings)); 

I am the Author of ExistAll.SimpleConfig . SimpleConfig is exactly what is needed for Configuration / Settings in a DI environment.

Take a look to see if it's what you need

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM