The options stuff is a car crash.
On my last project, I just assigned the configs to a static class that's available everywhere and the code was just simply much cleaner.
You really don't - just inject your populated config object where you need it.
So it sounds like basically he's not using DI (is just using it to pass stuff to controllers) and is surprised that using a library designed around DI is awkward. The correct solution is use DI to construct that hierarchy and then you can just request IOptions at the bottom/where you need it.
This is precisely why I jumped ship 5 years ago to Go.
Plenty of other people piping up saying they also find this bad abstraction obnoxious, sorry you can't empathise and understand we all have difference preferences.
I'm not sure if maybe you're referring to the Options<T> stuff?
The way I do it is pretty simple.
1. Create a POCO that represents your config. You can have properties for bested configs if you want, e.g. SecurityConfig, MessageBusConfig 2. When the app starts, use a ConfigurationBuilder to build an IConfiguration from whatever Co fig sources you want - typically JSON files and env vars 3. Bind the IConfiguration to your POCO 4. Configure both IConfiguration and the POCO as singletons
Now you can inject the POCO config object wherever you want it, or the IConfiguration should you need it. I feel like this is simple, and works well for dev, test and prod.