In console application with dependency injection with Options pattern I'm trying to load user input. How can I make "factory like" resolving of
IOptions<ArgSettings>
to load input arguments. If required input arguments are not provided (null or not valid) then use default settings from appsettings.json?
public class ArgSettings
{
public string Name { get; set; }
public string Region { get; set; }
}
public interface IService
{
void DoSomthing();
}
public class MyService: IService
{
private readonly ArgSettings _argSettings;
public MyService(IOptions<ArgSettings> cfg)
{
_argSettings = cfg.Value;
}
public void DoSomthing()
{
}
}
public class Program
{
static void Main(string[] args)
{
ArgSettings argsSettings = BindArgsSettings(Environment.GetCommandLineArgs());
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
var configurationRoot = context.Configuration;
services.Configure<ArgSettings>(
configurationRoot.GetSection("Defaults:Args"));
services.AddTransient<IService, MyService>();
}).Build();
}
}
default config section in appsettings.json:
...
"Defaults": {
"Args": {
"Name": "John",
"Region": "USA"
}
}
...
First, when you use IOptions.. you have to use the ".Value"
below code is from : https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-6.0
private readonly PositionOptions _options;
public Test2Model(IOptions<PositionOptions> options)
{
_options = options.Value;
}
Or more generically (less ambiguous):
public class MyCoolClass
{
private readonly MyWhateverSettings _settings;
public MyCoolClass(IOptions<MyWhateverSettings> options)
{
_settings = options.Value;
}
(back to your code)
While I see this code above:
BindArgsSettings(Environment.GetCommandLineArgs());
I don't see what you are doing with the "result of that call".
Ok, here is a Unmodified Microsoft Sample: (from https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-6.0 )
using ConfigSample.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<PositionOptions>(
builder.Configuration.GetSection(PositionOptions.Position));
var app = builder.Build();
(the above being used as a sanity check)
What I think you want:
/* has the possibility to be null, if the user "passes" on customizing it */
ArgSettings myArgsSettings = BindArgsSettings(Environment.GetCommandLineArgs());
if (null == myArgsSettings)
{
/* user "passed up" doing it manually, so go get the "Defaults" */
myArgsSettings = configurationRoot.GetSection("Defaults:Args");
}
/* now DI inject */
builder.Services.Configure<ArgSettings>(myArgsSettings);
Aka, you are doing something with the result (from 'BindArgsSettings(Environment.GetCommandLineArgs()') .. aka, what has hydrated the 'myArgsSettings' variable. (the first hydration of myArgsSettings that is)
Or below is a "less ambiguous" implementation:
/* has the possibility to be null, if the user "passes" on customizing it */
ArgSettings userProvidedArgsSettings = BindArgsSettings(Environment.GetCommandLineArgs());
ArgSettings fromJsonArgSettings = null;
if (null == userProvidedArgsSettings)
{
/* user "passed up" doing it manually, so go get the "Defaults" */
fromJsonArgSettings = configurationRoot.GetSection("Defaults:Args");
}
if (null == userProvidedArgsSettings && null == fromJsonArgSettings)
{
throw new ArgumentNullException("Guh, Both UserProvider AND fromJson are null.", (Exception) null);
}
/* now DI inject */
if (null != userProvidedArgsSettings)
{
builder.Services.Configure<ArgSettings>(userProvidedArgsSettings);
}
if (null != fromJsonArgSettings)
{
builder.Services.Configure<ArgSettings>(fromJsonArgSettings);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With