Reputation: 1122
When I have nested classes where children need some of the configuration settings (i.e., settings written in appsettings.json
), do I need to make a bucket relay to pass configuration to children classes?
I don't think the example below is a smart way. Is there any better practice?
Startup.cs
public Startup(IConfiguration configuration, ...)
{
...
this.Configuration = configuration;
...
}
Parent.cs
public class Parent
{
public Parent(IConfiguration configuration)
{
_configuration = configuration;
}
private IConfiguration _configuration;
private ChildOne _childOne;
private ChildTwo _childTwo;
public void InitializeChildren()
{
_childOne = new ChildOne(_configuration);
_childTwo = new ChildTwo(_configuration);
}
}
ChildOne.cs
public class ChildOne{
public ChildOne(IConfiguration configuration){
_propOne = configuration.GetSection("brahbrah").Value;
}
private string _propOne;
}
Upvotes: 3
Views: 2845
Reputation: 764
Domain objects / models are nothing more than data containers. These data containers can have a need for data but should not be dependent on dependency injection (directly) for this data because they are at the core of your application. A change in your model (or it's dependencies) will most likely result in bigger changes.
As you show in your examples you want to instantiate your models using the new
operator and pass the IConfiguration as a parameter. By requiring IConfiguration in your data container you create a situation where your model will need extensive checking if the returned result exists and if every property in it exists and afterward setting the appropriate values in the data container.
A better solution to this problem is by registering a dedicated config class, which we will call BrahBrahConfig to match your example, in the dependency injection framework.
public static IServiceCollection SetupDependencyInjection(this
IServiceCollection services, IConfiguration config)
{
services.Configure<BrahBrahConfig>(config.GetSection("brahbrah"));
return services;
}
In the example above you see the use of an overload for IServiceCollection Configure<TOptions>(this IServiceCollection services, IConfiguration config)
which can be found in the nuget package "Microsoft.Extensions.Options.ConfigurationExtensions".
This overload enables you to directly inject an instance of IOptions into the constructor of your choice.
private BrahBrahConfig _config;
public Parent(IOptions<BrahBrahConfig> config)
{
_config = config?.Value ?? throw new ArgumentNullException(nameof(config));
}
So after registering this in your startup.cs you can use IOptions as parameter in the Parent constructor and use these settings to set the appropriate properties in your model.
Upvotes: 2
Reputation: 30665
Use dependency injection for your services, not for your Models. Models should not have any logic or service registration.
If you are talking about Service Classes, they are generally part of DI. you can register them to DI so that DI automatically resolves services upon instance construction.
For Instance,
public class Parent
{
public Parent(IConfiguration configuration, ChildOne childOne, ChildTwo childTwo)
{
_configuration = configuration;
_childOne = childOne;
_childTwo = childTwo;
}
private IConfiguration _configuration;
private ChildOne _childOne;
private ChildTwo _childTwo;
}
If you need to initialize ChildOne and ChildTwo by yourself, then you need to pass IConfiguration parameter or at least IServiceProvider in order to resolve required service(s)
Upvotes: 1