Welches Muster eignet sich zum Einfügen von Loggern in dynamisch erkannten .NET Core-Klassenbibliotheken, die von ASP.NET Core-Webanwendungen aufgerufen werden?

8

Überblick

Ich versuche, eine Reihe von Projekten basierend auf .NET Framework auf .NET Core zu portieren. Dies umfasst die Portierung einer Reihe von Klassenbibliotheken sowie von Konsolen / Web-Anwendungen auf oberster Ebene, die diese Bibliotheken nutzen.

Ein Teil meiner Anforderungen besteht darin, dass meine Top-Level-Anwendungen ein pluginbasiertes System unterstützen sollten, bei dem ich die Funktionalität einfach austauschen kann, indem ich auf verschiedene Teilmengen dieser Klassenbibliotheken referenziere. Ich habe MEF dafür benutzt. Zum Beispiel beinhaltet eine meiner ASP.NET Core-Webanwendungen die Kommunikation mit Geräten über ein ICommunicationService , und ich habe verschiedene Nuget-Pakete, die verschiedene Implementierungen dieses Dienstes exportieren:

%Vor%

Klassenbibliotheken neu gestalten

Im Moment verweisen diese Klassenbibliotheken auf Common.Logging und instanziieren Logger als schreibgeschützte statische Felder:

%Vor%

Ich habe Log4Net in meinen Top-Level-Anwendungen verwendet und die Protokollierung in meinen Klassenbibliotheken erleichtert, indem ich auf den Common.Logging.Log4Net Adapter verwiesen habe.

Ich weiß jedoch, dass ASP.NET Core auf Microsofts neuem Protokollierungs-Abstraktions-Framework Microsoft.Extensions.Logging angewiesen ist und dass ASP.NET Core-Anwendungen so konzipiert sein sollten, dass sie die Protokollierung über Konstruktorabhängigkeitsinjektion von Protokollierern wie folgt unterstützen:

%Vor%

Ich bin mir nicht ganz sicher, welche Kombination von Logging-Frameworks ich in meinen neuen .NET Core-Bibliotheken und -Anwendungen verwenden soll ( siehe diesen verwandten Post ), aber ich bin gelehnt in Richtung Umstellung von Common.Logging zu Microsoft.Extensions.Logging innerhalb meine Klassenbibliotheken. In diesem Fall frage ich mich, wie ich mit der Instanziierung von Loggern umgehen soll. Wäre so etwas angebracht?

%Vor%

Mit anderen Worten: Soll ich alle meine Klassenbibliotheken, die protokolliert werden müssen, so konfigurieren, dass diese Logger während der Konstruktion injiziert werden?

Verwende Klassenbibliotheken

Basierend auf dieser Antwort auf eine ähnliche Frage habe ich das Gefühl, dass der oben beschriebene Ansatz in die richtige Richtung geht. Ich bin mir jedoch nicht sicher, wie ich Dienste, die innerhalb von Klassenbibliotheken innerhalb einer ASP.NET Core-Anwendung definiert sind, konsumieren und instanziieren würde.

ASP.NET Core verwendet einen eigenen Abhängigkeitsinjektionsdienst, der vollständig von MEF getrennt ist. Ich kann nicht einfach aus zwei Gründen etwas wie services.AddSingleton<ICommunicationService, UsbCommunicationService>(); in meine Webanwendung schreiben:

  1. Die Idee ist, ein pluginbasiertes System zu unterstützen, in dem Plugins dynamisch erkannt werden und daher nicht von der "core" -Anwendung selbst hart referenziert werden können.

  2. Die anderen Abhängigkeiten für UsbCommunicationService - IUsbMessageEncoder und IUsbMessageDecoder - sind dem Service Injector von ASP.NET Core nicht bekannt und würden nicht aufgelöst.

Ebenso kann ich MEF nicht verwenden, um eine Instanz von UsbCommunicationService zu erhalten, da der Verweis auf ILogger<UsbCommunicationService> nicht aufgelöst werden kann.

Zusammenfassung

Kurz gesagt, ich versuche, Lösungen für Folgendes zu finden:

  • Erleichterung der Protokollierung in .NET Core-Bibliotheken mit maximaler Flexibilität für Protokollanbieter.
  • Zulassen, dass die Logger diesen Klassenbibliotheken durch Dependency-Injection zur Verfügung gestellt werden.
  • Top-Level-ASP.NET-Core- oder .NET Core-Konsolenanwendungen dürfen diese .NET-Core-Bibliotheken zur Laufzeit dynamisch erkennen und laden und alle mit Loggern oder Loggerfactorys versorgen, damit der Top-Level-Applikation und alle geladenen Plugins verwenden einen gemeinsamen Logging-Provider (zB Serilog, NLog, Log4Net, etc.).
    • Wenn ich zum Beispiel Log4nets ColoredConsoleAppender verwenden möchte, sollte ich alle ASP.NET-Protokolle und Klassenbibliothekslogs in derselben Konsole sehen.
Tagc 07.10.2016, 11:50
quelle

1 Antwort

2

Microsoft.Extensions.Logging ist nicht unbedingt ein Protokollierungsframework; Es ist eine Fassade. Es gibt eingebaute Implementierungen für Dinge wie Debug , Trace , Console usw., aber das ist nur für die Einfachheit. In der Praxis würden Sie wahrscheinlich etwas wie Serilog anschließen. Serilog ist das, was tatsächlich die Protokollierung behandelt, während Microsoft.Extensions.Logging nur eine abstrahierte Art der "Protokollierung" bietet, ohne dass Ihr App-Code tatsächlich explizit von der API von Serilog abhängen muss.

Common.Logging ist auch eine Fassade, wo Sie in diesem Fall log4net als den eigentlichen Logger gewählt haben. Das kann jedoch geändert werden. In Anbetracht dessen haben Sie ein paar mögliche Wege, die Sie nehmen können.

  1. Schalten Sie Microsoft.Extensions.Logging mit Common.Logging in Ihrer ASP.NET Core App aus. Ja, das kannst du tun. Persönlich denke ich, Microsoft.Extensions.Logging ist besser , aber Sie können verwenden, was Sie wollen.

  2. Schalten Sie Common.Logging mit Microsoft.Extensions.Logging in Ihren Klassenbibliotheken aus. Wenn Sie sie trotzdem umschreiben, ist das vielleicht am sinnvollsten, aber es beinhaltet auch die größte Reibung, was die Dinge betrifft, die in Ihrem Code geändert werden müssen.

  3. Schreiben Sie einen Adapter für Common.Logging, der Microsoft.Extensions.Logging verwendet. Dies ist zugegebenermaßen ein bisschen Meta, aber es ist technisch gesehen nichts falsch daran, einfach eine Fassade zu verwenden, um mit einer anderen Fassade zu arbeiten, um schließlich mit einem bestimmten Protokollierungs-Framework zu arbeiten. Das ist der ganze Punkt des Adaptermusters. Dadurch erhalten Sie auch das Beste aus beiden Welten: Sie müssen nicht viel in Ihren Bibliotheken oder Ihrer ASP.NET Core App ändern. Aufgrund der vielen Fassaden im Spiel erhöht es jedoch die Entropie Ihres Codes. Obwohl es unmöglich ist, dies zu sagen, sehe ich Common.Logging in Zukunft nicht weiter. Jetzt, da Microsoft eine fast eingebaute Fassade hat, erwarte ich, dass das ziemlich dominieren wird. Es könnte für den besten sein, jetzt zu springen, während Sie bereits einige Nacharbeit machen.

Chris Pratt 29.03.2018, 15:33
quelle