Vediamo se riesco a spiegarmi.
Sono ancora un novellino di ASP.NET Core ma da quello che ho capito, registrando una classe come servizio la DI puo' essere utilizzata solo nel costruttore di un Controller, Middleware, View, Hosted Service.
Riprendo un esempio che hai inserito in una risposta nel forum.
Diciamo che ho definito questa Appsettings:
{
"ConnectionStrings": {
"DefaultConnection": "Server=abca;database=CustomerDB;Password=xyz;User ID=sa"
},
"Smtp": {
"Host": "smtp.example.com",
"Port": 25,
"Username": "Pippo",
"Password": "Puppo",
"UseSSL": false
},
"AltraProprietà": "Whatever",
...
}
Definisco la classe SmtpOptions che riflette i valori dell'Appsettings
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; }
}
Definisco questa interfaccia e la classe per l'invio email:
public interface ISmtpClient {
Task SendMail(string from, string to, string subject, string body);
}
public class SmtpClient : ISmtpClient
{
private readonly IOptionsMonitor<SmtpOptions> smtpOptions;
public SmtpClient(IOptionsMonitor<SmtpOptions> smtpOptions)
{
this.smtpOptions = smtpOptions;
}
public async Task SendMail(string from, 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
...
}
}
Infine registro il servizio
public void ConfigureServices(IServiceCollection services)
{
...
//Registro l'SmtpClient come servizio
services.AddTransient<ISmtpClient, SmtpClient>();
//Registro la configurazione per SmtpOptions, che mi permettera' di usare il servizio IOptionsMonitor
services.Configure<SmtpOptions>(Configuration.GetSection("Smtp"));
}
Adesso definisco una Razor Pages per l'invio di email, definisco l'evento OnPost per l'invio e la DI nel costruttore della View:
public class ContactModel : PageModel
{
private readonly ISmtpClient _smtpClient;
public ContactModel(ISmtpClient smtpClient)
{
_smtpClient = smtpClient;
}
[BindProperty] public string From { get; set; }
[BindProperty] public string To { get; set; }
[BindProperty] public string Subject { get; set; }
[BindProperty] public string Email { get; set; }
public async Task<IActionResult> OnPost()
{
await _smtpClient.Send(From, To, Subject, Email);
return RedirectToPage("Thanks");
}
}
E fin qui funziona tutto per bene.
Adesso viene fatta una richiesta: registrare nel database una log con l'esito dell'invio email.
A me vengono in mente due soluzioni.
Soluzione 1.1. creare una classe che registra nel db la log dell'email:
public class LogEmail
{
private readonly string connectionString = ??
private readonly string _from;
private readonly string _to;
private readonly string _subject;
private readonly string _email;
private readonly bool _esito;
public LogEmail(from, to, subject, email, esito)
{
_from = from;
_to = to;
_subject = subject;
_email = email;
_esito = esito;
}
public int Registra()
{
// istruzioni per l'insert
...
}
}
2. aggiornare la classe SmtpClient per gestire la registrazione della log:
public class SmtpClient : ISmtpClient
{
...
public async Task SendMail(string from, 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
...
// scrittura della log email
LogEmail log = new LogEmail(from, to, subject, body, esito);
log.Registra();
}
}
Domanda.La classe LogEmail come ottiene la stringa di connessione?
Potrei definire la classe LogEmail come servizio per poter accedere all'Appsettings.
Ma nella classe SmtpClient non posso sfruttare la DI, giusto?
Dovrebbe essere la classe SmtpClient che accede all'Appsettings e passa la stringa di connessione nel costruttore di LogMail.
Soluzione 2.1. creare una classe che registra nel db la log dell'email (come prima)
2. definire la classe LogEmail come servizio che nel costruttore accede alla configurazione
3. richiamare la scrittura della log nella View ContactModel, sfruttando la DI nel costruttore della classe LogEmail
Osservazione.
Io avrei preferito poter accedere all'Appsettings all'interno della classe senza dipendenze esterne.
Potrei al esempio spostare la classe LogEmail in una libreria separata.
Sperando di essere stato sufficientemente chiaro, che soluzione proporresti?
Grazie
salvo