Search code examples
c#.netdependency-injection.net-5

Microsoft generic host app runtime configuration: Do I really need to spray "IOptions<>" throughout my code base?


I'm trying to use Microsoft's "hosting/logging/configuration/dependency injection" thing for a new console app in .Net 5.0. A little background first: I'm totally new to all that, and I have never used any of the similar stuff that's apparently long been available in ASP.NET (in fact I don't think I've ever even used ASP.NET at all, and if I did, it was long long ago, and in a very small way). With that said:

I feel like I'm missing something regarding configuration, specifically with binding a section of appsettings.json (or whatever) to an options class. Let's say I have a preexisting class -- not specifically intended for use with Microsoft's DI/etc. framework -- that takes some sort of options class in its constructor:

public X(XOptions options) {
   this.Blah = options.OneThirtySeventhBlah * 37;
}

I found various examples of how to get stuff from appsettings.json into my code:

services.Configure<XOptions>(options => hostContext.Configuration.GetSection("X").Bind(options));

But upon running with that, I found (to my surprise) that it wouldn't work with my preexisting X class. To get it to work, I also had to change X's constructor (or, I guess, at least add a new constructor) to take an IOptions<XOptions> instead of simply taking an XOptions:

public X(IOptions<XOptions> options) {
   this.Blah = options.Value.OneThirtySeventhBlah * 37;
}

That works fine and all, but... am I missing something here? Do I really have to change my pre-existing class (which, again, is not specifically for use in this type of framework) to have all this additional Microsoft stuff as a dependency?

I suppose I could instead write a MicrosoftifiedX class, taking an IOptions<XOptions> in its constructor and implementing the same interface as X does, and make that part of an optional package, but... like I said, I feel like I'm missing something. Can I really not just bind the configuration directly to XOptions? If I can, how?

And if I can't, then I can't help but imagine that there might be some standard (or at least reasonably widespread) framework/pattern/library for dealing with this that's less tedious than my MicrosoftifiedX idea. Does anyone know of such a thing? Thanks.


Solution

  • Yes you can and, in my opinion you should, prevent from letting your line-of-business classes take a dependency on IOption<T>. Instead, register the options object as singleton:

    XOptions xoptions = config.GetSection("SectionName").Get<XOptions>();
    
    // Verify XOptions here (if required)
    
    // Register XOptions as singleton
    services.AddSingleton<XOptions>(xoptions);
    services.AddTransient<IX, X>(); // X takes a dependency on XOptions