Ciao,
a capire come fare ad accedere ai valori presenti nel file appsettings.json da una classe qualsiasi
C'è una soluzione brutta e perciò non te la dico. Quello che dovresti fare, invece, è registrare la tua "classe qualsiasi" come servizio nel meccanismo di dependency injection di ASP.NET Core.
Supponiamo che tu abbia una classe SmtpClient che usi per inviare le email e che internamente necessita dei valori di configurazione situati nel file appsettings.json (es. nome host, porta, user, password, ecc..). Per prima cosa, estrai un'interfaccia che servirà a migliorare il disaccoppiamento tra i componenti e perciò aumenterà la testabilità della tua applicazione.
public interface ISmtpClient {
Task SendMail(string to, string subject, string body);
}
Ora fai implementare questa interfaccia alla tua classe. Inoltre, nota come nel costruttore della classe SmtpClient ho esplicitato una dipendenza da IOptionsMonitor<SmtpOptions>, un servizio che ti permette di recuperare la configurazione corrente (si aggiorna dopo eventuali modifiche a caldo apportate all'appsettings.json) e che verrà iniettato dalla dependency injection di ASP.NET Core.
public class SmtpClient : ISmtpClient {
private readonly IOptionsMonitor<SmtpOptions> smtpOptions
public SmtpClient(IOptionsMonitor<SmtpOptions> smtpOptions) {
this.smtpOptions = smtpOption;
}
public async Task SendMail(string to, string subject, string body) {
//Accedo alla configurazione
//Prima ottengo la configurazione attuale dal monitor
var config = smtpOptions.CurrentValue;
//E poi leggo i singoli valori
var host = config.Host;
var port = config.Port;
var username = config.Username;
var password = config.Password;
var useSSL = config.UseSSL;
//Implementazione di invio email qui, usando i parametri ottenuti dalla configurazione
}
}
La classe SmtpOptions che ho menzionato nell'esempio qui sopra è una classe personalizzata che riflette la struttura di un ramo dell'appsettings.json. Supponiamo che l'appsettings.json sia fatto così:
{
"Smtp": {
"Host": "smtp.example.com",
"Port": 25,
"Username": "Pippo",
"Password": "Puppo",
"UseSSL": false
},
"AltraProprietà": "Whatever",
...
}
Allora la classe chiamata (ad esempio) SmtpOptions avrà queste proprietà, che riflettono tali e quali il nome e il tipo di dati trovati nel json. Io la creo a mano ma da Visual Studio te la puoi anche creare velocemente dal menu Modifica -> Incolla speciale -> Incolla JSON come classi, dopo aver copiato il json ovviamente.
public class SmtpOptions {
public string Host { get; set; }
public int Port { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool UseSSL { get; set; }
}
Adesso è il momento di tirare le fila: tutto quanto va registrato come servizio dal metodo ConfigureServices della classe Startup.
public void ConfigureServices(IServiceCollection services)
{
...
//Registro l'SmtpClient come servizio
services.AddTransient<ISmtpClient, SmtpClient>();
//Registro la configurazione per SmtpOptions, che mi permetterà di usare il servizio IOptionsMonitor
services.Configure<SmtpOptions>(Configuration.GetSection("Smtp"));
...
}
A questo punto, ora che il servizio ISmtpClient è stato registrato, lo puoi ricevere come parametro del costruttore di un qualsiasi altro componente dell'applicazione, come: Controller, Middleware, View (meglio non inviare un'email da una view, ma tant'è), Hosted Service e qualsiasi altro servizio che sia stato esso stesso registrato con la dependency injection.
ciao,
Moreno
Modificato da BrightSoul il 18 luglio 2018 21.59 -