Creating classes and classes is very object-oriented and follows the single-responsibility principle, among others. However, dividing responsibilities into programming concerns is not always what leads to the easiest code to understand because it creates a lot of classes and files, often spread across multiple layers and more.An alternative is to regroup the initialization and validation […]
Workaround – Injecting options directly – Options, Settings, and Configuration
The only negative point about the .NET Options pattern is that we must tie our code to the framework’s interfaces. We must inject an interface like IOptionsMonitor<Options> instead of the Options class itself. By letting the consumers choose the interface, we let them control the lifetime of the options, which breaks the inversion of control, […]
Project – OptionsValidationFluentValidation – Options, Settings, and Configuration
In this project, we validate options classes using FluentValidation. FluentValidation is a popular open-source library that provides a validation framework different from data annotations. We explore FluentValidation more in Chapter 15, Getting Started with Vertical Slice Architecture, but that should not hinder you from following this example.Here, I want to show you how to leverage […]
Validation types – Options, Settings, and Configuration
To implement options validation types or options validators, we can create a class that implements one or more IValidateOptions<TOptions> interfaces. One type can validate multiple options, and multiple types can validate the same options, so the possible combinations should cover all use cases.Using a custom class is no harder than using data annotations. However, it […]
Configuring the options – Options, Settings, and Configuration
We want two different options to test out many possibilities: To achieve this, we must add the following lines in the Program.cs file: const string NamedInstance = “MyNamedInstance”;builder.Services .Configure<ConfigureMeOptions>(builder.Configuration .GetSection(“configureMe”)) .Configure<ConfigureMeOptions>(NamedInstance, builder.Configuration .GetSection(“configureMe”)); The preceding code registers a default instance (highlighted code) and a named instance. Both use the configureMe configuration sections and so start […]
Project – OptionsConfiguration – Options, Settings, and Configuration
Now that we have covered basic usage scenarios, let’s attack some more advanced possibilities, such as creating types to configure, initialize, and validate our options.We start by configuring options which happen in two phases: In a nutshell, the post-configuration phase happens later in the process. This is a good place to enforce that some values […]
Named options – Options, Settings, and Configuration
Now, let’s explore named options by configuring two more instances of the MyOptions class. The concept is to associate a configuration of the options with a name. Once that is done, we can request the configuration we need. Unfortunately, the ways we explore named options and most online examples break the Inversion of Control principle. […]
IOptionsFactory – Options, Settings, and Configuration
This interface is a factory, as we saw in Chapter 7, Strategy, Abstract Factory, and Singleton, and in Chapter 8, Dependency Injection, we use factories to create instances; this interface is no different. Unless necessary, I suggest sticking with IOptionsMonitor<TOptions> or IOptionsSnapshot<TOptions> instead. How the factory works is simple: the container creates a new factory […]
Learning the building blocks – Options, Settings, and Configuration
There are four main interfaces to use settings: IOptionsMonitor<TOptions>, IOptionsFactory<TOptions>, IOptionsSnapshot<TOptions>, and IOptions<TOptions>. We must inject that dependency into a class to use the available settings. TOptions is the type that represents the settings that we want to access.The framework returns an empty instance of your options class if you don’t configure it. We learn […]
Revisiting the Factory pattern – Dependency Injection
A factory creates other objects; it is like a literal real-world factory. We explored in the previous chapter how to leverage the Abstract Factory pattern to create families of objects. A factory can be as simple as an interface with one or more Create[Object] methods or, even more, a simple delegate. We explore a DI-oriented […]