.NET Core DI et sous-classes

Nov 21 2020

Nouveau sur .NET Core ici. J'ai recherché une autre documentation, un fil de discussion ou un guide qui répond à mes questions mais je n'en trouve pas, si vous pensez que c'est le cas, veuillez le signaler.

J'essaie de créer une simple application console .NET 5 avec DI et je reste littéralement coincé dans la structuration des classes avec la journalisation.

  1. Est-ce la bonne façon de passer un enregistreur (ou tout autre service) à une sous-classe à l'aide de DI dans .NET Core? Selon le code ci-dessous, dans mon constructeur de classe parent, je prends un ILogger supplémentaire pour chaque sous-classe, par exemple. ILogger<SubClass>?

    public TestClass(ILogger<TestClass> log, ILogger<SubClass> subClassLog, IConfiguration config)
    
  2. Comment initialiser un enregistreur dans mon proc statique StaticProc?

    public static async Task<bool> StaticProc()
    

Program.cs:

    en utilisant Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    en utilisant Microsoft.Extensions.Hosting;
    en utilisant Microsoft.Extensions.Logging;
    en utilisant le système;
    en utilisant System.IO;
    using System.Threading.Tasks;
    
    espace de noms ConsoleApp1
    {
        programme de classe
        {
            Tâche principale statique asynchrone (string [] args)
            {
                var builder = nouveau ConfigurationBuilder ();
                BuildConfig (constructeur);
    
                var hôte = Host.CreateDefaultBuilder ()
                    .ConfigureServices ((contexte, services) =>
                    {
                        services.AddTransient <ITestClass, TestClass> ();
                        services.AddTransient <ISubClass, SubClass> ();
                    })
                    .ConfigureLogging (logBuilder =>
                    {
                        logBuilder.SetMinimumLevel (LogLevel.Trace);
                        logBuilder.AddLog4Net ("log4net.config");
                    })
                    .Construire();
    
                var log = host.Services.GetService <ILoggerFactory> () .CreateLogger <Programme> ();
    
                log.LogInformation ($"Application Started");
    
                var svc = ActivatorUtilities.CreateInstance<TestClass>(host.Services);
                await svc.Run();
    
                log.LogInformation($«Application terminée»);
            }
    
            static void BuildConfig (générateur IConfigurationBuilder)
            {
                builder.SetBasePath (Directory.GetCurrentDirectory ())
                    .AddJsonFile ("appsettings.json", facultatif: false, reloadOnChange: true)
                    .AddJsonFile ($ "appsettings. {Environment.GetEnvironmentVariable (" ASPNETCORE_ENVIRONMENT ") ??" Development "}. Json", optionnel: true)
                    .AddEnvironmentVariables ();
            }
        }
    }

TestClass.cs:

    en utilisant Microsoft.Extensions.Configuration;
    en utilisant Microsoft.Extensions.Logging;
    using System.Threading.Tasks;
    
    espace de noms ConsoleApp1
    {
        classe publique TestClass: ITestClass
        {
            privé en lecture seule ILogger <TestClass> _log;
            private readonly ILogger <SubClass> _subClassLog;
            privé en lecture seule IConfiguration _config;
    
            public TestClass (journal ILogger <TestClass>, ILogger <SubClass> subClassLog, configuration IConfiguration)
            {
                _log = journal;
                _subClassLog = subClassLog;
                _config = config;
            }
    
            exécution de la tâche publique async ()
            {
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogDebug ("Débogage de boucle {loopNumber}", i);
    
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogInformation ("Informations sur la boucle {loopNumber}", i);
    
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogWarning ("Loop warn {loopNumber}", i);
    
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogError ("Erreur de boucle {loopNumber}", i);
    
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogCritical ("Boucle critique {loopNumber}", i);
    
                var subClass = new SubClass (_subClassLog, _config);
                attendre subClass.AnotherProc ();
    
                attendre SubClass.StaticProc ();
            }
        }
    }

SubClass.cs:

    en utilisant Microsoft.Extensions.Configuration;
    en utilisant Microsoft.Extensions.Logging;
    en utilisant le système;
    using System.Threading.Tasks;
    
    espace de noms ConsoleApp1
    {
        classe publique SubClass: ISubClass
        {
            privé en lecture seule ILogger <SubClass> _log;
            privé en lecture seule IConfiguration _config;
    
            public SubClass (journal ILogger <SubClass>, configuration IConfiguration)
            {
                _log = journal;
                _config = config;
            }
    
            public async Tâche AnotherProc ()
            {
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogDebug ("Débogage de boucle {loopNumber}", i);
    
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogInformation ("Informations sur la boucle {loopNumber}", i);
    
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogWarning ("Loop warn {loopNumber}", i);
    
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogError ("Erreur de boucle {loopNumber}", i);
    
                for (int i = 0; i <_config.GetValue <int> ("Boucle"); i ++)
                    _log.LogCritical ("Boucle critique {loopNumber}", i);
            }
    
            Tâche publique statique async <bool> StaticProc ()
            {
                var returnBool = true;
    
                essayer
                {
                    lancer une nouvelle exception ("");
                }
                catch (Exception ex)
                {
                    returnBool = false;
    
                    // Pas d'instance, donc pas d'exception _log.
                    // Comment créer un ILogger autonome?
                }
    
                return returnBool;
            }
        }
    }

appsettings.json:

    {
      "Boucle": 15
    }

log4net.config:

    <? xml version = "1.0" encoding = "utf-8"?>
    <log4net>
        <appender name = "Info" type = "log4net.Appender.RollingFileAppender">
            <seuil value = "DEBUG" />
            <param name = "File" value = "App_Data \\ Log \\ Info.log" />
            <param name = "AppendToFile" value = "true" />
            <maximumFileSize value = "5120 Ko" />
            <lockModel type = "log4net.Appender.FileAppender + MinimalLock" />
            <maxSizeRollBackups value = "1000" />
            <layout type = "log4net.Layout.PatternLayout">
                <conversionPattern value = "% d {aaaa-MM-jj HH: mm: ss} - [% t]% -5p% c% x -% m% n" />
            </layout>
        </appender>
        <appender name = "Error" type = "log4net.Appender.RollingFileAppender">
            <seuil valeur = "Erreur" />
            <param name = "File" value = "App_Data \\ Log \\ Error.log" />
            <param name = "AppendToFile" value = "true" />
            <maximumFileSize value = "5120 Ko" />
            <lockModel type = "log4net.Appender.FileAppender + MinimalLock" />
            <maxSizeRollBackups value = "1000" />
            <layout type = "log4net.Layout.PatternLayout">
                <conversionPattern value = "% d {aaaa-MM-jj HH: mm: ss} - [% t]% -5p% c% x -% m% n" />
            </layout>
        </appender>
        <racine>
            <appender-ref ref = "Info" />
            <appender-ref ref = "Erreur" />
        </root>
    </log4net>

Réponses

Martin Nov 21 2020 at 00:13

Sommaire

Vous pouvez également injecter un ILoggerFactoryau lieu de ILogger:

public TestClass(ILoggerFactory loggerFactory, IConfiguration config)
{
     // create a class logger
     _log = loggerFactory.CreateLogger<TestClass>();

     // and whenever you need a new instance of a special class logger use this:
     _subClassLog = loggerFactory.Create<SubTestClass>();
     _config = config;
}

Mais sachez que cela crée une nouvelle instance de ILogger. Connexion asp net core Dans votre cas, si vous avez vraiment besoin de la méthode statique avec un enregistreur, créez-la uniquement si elle existe déjà:

private static readonly ILogger<SubClass> _log;
private readonly IConfiguration _config;

public SubClass(ILoggerFactory loggerFactory, IConfiguration config)
{
     _log = _log ??= loggerFactory.CreateLogger<SubClass>();
     _config = config;
}

Mais je préfère ou mieux vous conseiller de le faire sans avoir de statique et d'enregistrer simplement le service en tant que singleton.

Exemple 1

J'ai ajouté un exemple complet ici: dotnet fiddle Exemple 1 Également avec la DI de travail pour les applications de console comme mentionné dans les commentaires.

Exemple 2

Imo, vous ne devriez pas l'utiliser avec des méthodes statiques. Regardez simplement mon deuxième exemple ici dotnet fiddle Exemple 2