Adding support for declaratively injecting from appsettings to FrenziedMarmot.DependencyInjection

Aaron Moore
2 min readAug 11, 2021

In version 1.0.1 of FrenziedMarmot.DependencyInjection we added the ability to decorate classes to be deserialized from your appsettings.json file and injected using the Options Pattern. It does so via a new attribute called [InjectableOptions]. This is different from injecting a service in that it supports the full options pattern including IOptions<T>, OptionsSnapshot<T>, and IOptionsMonitor<T>.

To use it, simply ensure you’ve installed (or updated) the FrenziedMarmot.DependencyInjection package from Nuget or from Github Packages. From that point, there are 2 steps.

1) Decorate your classes for deserialization

First, you need to decorate the classes you’re going to use to hold the settings. Say for example we have this in our appsettings.json file:

{
"SomeApiOptions": {
"Host": "https://example.com",
"Port": "80"
}
}

And we have this model:

public class SomeApiOptions
{
public string Host { get; set; }
public string Port { get; set; }
}

What we need to do in order to allow the library to pick it up is to mark it up with the new attribute:

[InjectableOptions]
public class SomeApiOptions
//...

The attribute will fall back to the class it’s attached to as it’s target implementation and the name of the target implementation as it’s path. Both of these can be overridden. Say, for example, that our model class is defined in an assembly outside our control. We can provide it anyway and the name of our settings doesn’t have to match the implementation’s class name.

[InjectableOptions("SomeApiOptions", typeof(ThirdPartyOptionModel)]
public class Startup
//...

This attribute would look for the "SomeApiOptions" key in our appsettings.json and deserialize that into the model class specified.

2) Scan for the attribute

Attributes by themselves don’t DO anything. We need to scan for it. All the library needs is for the scan function to be called while you’re setting up the dependency injection.

services.ScanForOptionAttributeInjection(Configuration, GetType().Assembly);

This will pick up the types decorated with the attribute and now you can inject with the options pattern.

Example usage from above:

public MyApiController(IOptions<ThirdPartyOptionModel> opts)
{
Console.WriteLine($"{opts.Value.Host}:{opts.Value.Port}");
}

What’s the point?

The purpose of the library and this feature is so that as you create more models and services to inject, you don’t need to go back and edit Startup.cs every time. Some of the more complex configuration such as setting up Identity/Auth, Cors, etc. will inevitably result in having to code them into your startup file. But for the majority of injection it adds up.

Marking up my service with how it’s injected keeps the configuration alongside the service being injected, and keeps the startup file cleaner.

See https://github.com/FrenziedMarmot/DependencyInjection for the full, MIT-licensed source.

--

--