簡體   English   中英

如何使用 ASP.NET Core 中的 DI 將 email 提供程序添加到記錄器中?

[英]How to get an email provider into a logger using DI in ASP.NET Core?

抱歉,這對我來說有點新,所以我不太“明白”。

我已經有一個日志提供者

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddLogging(loggingBuilder =>
            {
                var loggingSection = Configuration.GetSection("Logging");
                loggingBuilder.AddFile(loggingSection);
                loggingBuilder.AddConsole();
                loggingBuilder.AddDebug();

我正在使用 package NReco.Logging.File 來定義AddFile等。

我想這樣做,以便也通過電子郵件將例外情況發送給我。 所以我按照https://learn.microsoft.com/en-us/do.net/core/extensions/custom-logging-provider創建了一個自定義記錄器。

 public sealed class EmailLoggerConfiguration
    {
        public int EventId { get; set; }

        public string EmailToSendTo { get; set; }
        public IEmailSender EmailSender { get; set; }
    }
    internal class EmailLoggingProvider : ILoggerProvider
    {
        private readonly IDisposable? _onChangeToken;
        private EmailLoggerConfiguration _currentConfig;
        private readonly ConcurrentDictionary<string, EmailLogger> _loggers =
            new(StringComparer.OrdinalIgnoreCase);
        private readonly IEmailSender emailSender;

        public EmailLoggingProvider(
            IOptionsMonitor<EmailLoggerConfiguration> config)
        {
            _currentConfig = config.CurrentValue;
            _onChangeToken = config.OnChange(updatedConfig => _currentConfig = updatedConfig);
            
        }

        public ILogger CreateLogger(string categoryName) =>
            _loggers.GetOrAdd(categoryName, name => new EmailLogger(name, GetCurrentConfig ));

        private EmailLoggerConfiguration GetCurrentConfig() => _currentConfig;

        public void Dispose()
        {
            _loggers.Clear();
            _onChangeToken?.Dispose();
        }
    }

    internal class EmailLogger : ILogger
    {
        private readonly string categoryName;
        private Func<EmailLoggerConfiguration> getCurrentConfig;
        IEmailSender emailSender;


        public EmailLogger(string categoryName, Func<EmailLoggerConfiguration> getCurrentConfig)
        {
            this.getCurrentConfig = getCurrentConfig;
            this.categoryName = categoryName;
            
        }

        public IDisposable? BeginScope<TState>(TState state) where TState : notnull => default!;

        public bool IsEnabled(LogLevel logLevel) => !String.IsNullOrEmpty(getCurrentConfig().EmailToSendTo);

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
        {
            var emailTo = getCurrentConfig().EmailToSendTo;
            //var emailServer = getCurrentConfig().EmailSender;
            if (!String.IsNullOrEmpty(emailTo) && exception != null)
            {
                emailSender.SendEmailAsync(emailTo, "Admin exception", exception.ToString());
            }
        }
    }


    public static class EmailLoggingExtensions
    {
        public static ILoggingBuilder AddEmailLogger(
            this ILoggingBuilder builder)
        {
            builder.AddConfiguration();

            builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, EmailLoggingProvider>());

            LoggerProviderOptions.RegisterProviderOptions<EmailLoggerConfiguration, EmailLoggingProvider>(builder.Services);

            return builder;
        }

        public static ILoggingBuilder AddEmailLogger(
            this ILoggingBuilder builder,
            Action<EmailLoggerConfiguration> configure)
        {
            builder.AddEmailLogger();
            builder.Services.Configure(configure);

            return builder;
        }
    }

您可以看到EmailLogger.Log需要emailSender ,它應該是一個IEmailSender ,但我無法弄清楚如何使用 DI 獲取它。

我知道你可以在 DI 中鏈接依賴關系但是???? 我不知道在這種情況下如何。

我試過這個

                loggingBuilder.AddEmailLogger(c =>
                {
                    c.EmailToSendTo = Configuration["Logging:Email:EmailToSendTo"];
                    c.EmailSender = new AuthMessageSender(????, Configuration);
                });

但這無濟於事,而且無論如何都不對。

實際上,默認情況下, EmailSenderIEmailSender的實現方法,用於調用SendEmailAsync()方法。 您不需要 go 並設置c.EmailSender = xxx

您可以考慮以下依賴注入方法:

public interface IEmailSender
{
    Task SendEmailAsync(string email, string subject, string message);
}
public class EmailSender : IEmailSender
{
    //...
    private readonly ILogger<EmailSender> logger;
    public EmailSender(ILogger<EmailSender> logger) {
        //...
        this.logger = logger;
    }

    public Task SendEmailAsync(string email, string subject, string message) {
        //...
    }
}

此時, IEmailSender將作為自定義接口存在,而不是繼承自Microsoft.AspNetCore.Identity.UI.Services

您需要將其注冊為服務:

services.AddTransient<IEmailSender, EmailSender>();

有用的網址:

添加ILogger發送email服務

我應該使用 IEmailSender 嗎?

在我的 Startup.cs 文件中使用 Configure() 中的 IEmailSender

希望這能幫助您更好地理解 IEmailSender 和依賴注入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM