Sie haben Recht, dass der Code nicht geschrieben funktioniert.Dieser Code verwendet eine Konfigurationsdatei (FileConfigurationSource) als Methode zum Konfigurieren der Enterprise Library.
Lassen Sie uns ein wenig tiefer graben und sehen, ob die programmatische Konfiguration funktioniert.
Wir werden die Fluent API verwenden, da es die bevorzugte Methode zur programmatischen Konfiguration ist:
var builder = new ConfigurationSourceBuilder();
builder.ConfigureLogging()
.WithOptions
.DoNotRevertImpersonation()
.FilterEnableOrDisable("EnableOrDisable").Enable()
.LogToCategoryNamed("General")
.WithOptions.SetAsDefaultCategory()
.SendTo.FlatFile("FlatFile")
.ToFile(@"fluent.log");
var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
var defaultWriter = new LogWriterFactory(configSource).Create();
defaultWriter.Write("Test1", "General");
var filter = defaultWriter.GetFilter<LogEnabledFilter>();
filter.Enabled = false;
defaultWriter.Write("Test2", "General");
Wenn Sie versuchen, diesen Code wird der Filter nicht aktualisiert werden - so ein weiteres Scheitern.
Lassen Sie uns versuchen, die „alten Schule“ programmatische Konfiguration zu verwenden, indem die Klassen direkt mit:
var flatFileTraceListener = new FlatFileTraceListener(
@"program.log",
"----------------------------------------",
"----------------------------------------"
);
LogEnabledFilter enabledFilter = new LogEnabledFilter("Logging Enabled Filter", true);
// Build Configuration
var config = new LoggingConfiguration();
config.AddLogSource("General", SourceLevels.All, true)
.AddTraceListener(flatFileTraceListener);
config.Filters.Add(enabledFilter);
LogWriter defaultWriter = new LogWriter(config);
defaultWriter.Write("Test1", "General");
var filter = defaultWriter.GetFilter<LogEnabledFilter>();
filter.Enabled = false;
defaultWriter.Write("Test2", "General");
Erfolg! Die zweite Nachricht ("Test2") wurde nicht protokolliert.
Also, was ist hier los? Wenn wir den Filter selbst instanziieren und ihn zur Konfiguration hinzufügen, funktioniert der Filterwert nicht, wenn er sich auf die Enterprise Library-Konfiguration verlässt.
Dies führt zu einer Hypothese: Bei der Verwendung der Enterprise Library-Konfiguration werden jedes Mal neue Filterinstanzen zurückgegeben. Daher hat das Ändern des Werts keine Auswirkungen auf die von Enterprise Library verwendete interne Instanz.
Wenn wir in den Enterprise Library Code graben wir (schließlich) auf LoggingSettings
Klasse und die BuildLogWriter
Methode. Dies wird verwendet, um den LogWriter zu erstellen. Hier ist, wo die Filter erstellt werden:
var filters = this.LogFilters.Select(tfd => tfd.BuildFilter());
So diese Linie die konfigurierte LogFilterData
verwendet, und den Aufruf der BuildFilter Methode des anwendbaren Filter zu instanziiert. In diesem Fall wird die BuildFilter
Methode der Konfigurationsklasse LogEnabledFilterData
BuildFilter
Methode gibt eine Instanz der LogEnabledFilter
:
return new LogEnabledFilter(this.Name, this.Enabled);
Das Problem mit diesem Code ist, dass this.LogFilters.Select
eine faule ausgewertete Aufzählung zurückzugibt, die LogFilters
und diese Aufzählung erzeugt wird geführt in der LogWriter, der für alle Filtermanipulationen verwendet werden soll. Jedes Mal, wenn auf die Filter verwiesen wird, wird die Aufzählung ausgewertet und eine neue Filterinstanz erstellt! Dies bestätigt die ursprüngliche Hypothese.
Um es explizit zu machen: Jedes Mal, wenn LogWriter.Write() aufgerufen wird, wird ein neues LogEnabledFilter
basierend auf der ursprünglichen Konfiguration erstellt. Wenn die Filter durch Aufruf von GetFilter()
abgefragt werden, wird basierend auf der ursprünglichen Konfiguration ein neuer LogEnabledFilter
erstellt. Alle Änderungen am Objekt, die von GetFilter()
zurückgegeben werden, haben keine Auswirkungen auf die interne Konfiguration, da es sich um eine neue Objektinstanz handelt und die Enterprise Library auf jeden Fall eine weitere neue Instanz auf dem nächsten Write()
-Aufruf erstellt.
Erstens ist das einfach falsch, aber es ist auch ineffizient, neue Objekte bei jedem Aufruf an Write()
zu erstellen, der mehrmals aufgerufen werden konnte.
Eine einfache Lösung für dieses Problem ist es, die LogFilters Aufzählung zu bewerten ToList()
durch den Aufruf:
var filters = this.LogFilters.Select(tfd => tfd.BuildFilter()).ToList();
Dies wertet die Aufzählung sichergestellt nur einmal, dass nur eine Filterinstanz erstellt wird. Dann funktioniert der GetFilter()
und Update-Filterwert-Ansatz in der Frage funktioniert.
Randy, danke für die ausführliche Erklärung! Ich habe den neuesten Quellcode für EL6 heruntergeladen, und ich habe dieses Update implementiert, aber ich kann den Quellcode nicht mit der BuildLibrary.bat auf meinem System erstellen. Könnten Sie bitte einen Blick auf diese [Frage] nehmen (http://stackoverflow.com/questions/39546020/how-to-rebuild-enterprise-library-6-on-win-8-and-vs2015) – Legends
Ok, erledigt. Ich habe es mit deiner Reparatur funktionieren lassen. Danke vielmals! – Legends
FYI, nach der Reparatur habe ich die Unit- und BVT-Tests erneut durchgeführt und sah keinen Bruch aufgrund der Änderung. –