Ведение журнала Enterprise Library 5.0 с использованием CustomTraceListener и ConfigurationSourceBuilder

Я пытаюсь создать библиотеку ведения журнала, которая использует блок кода ведения журнала Enterprise Library 5.0, и мне удалось создать CustomTraceListener, который работает, когда конфигурация поступает из файла конфигурации, но когда я пытаюсь настроить его с помощью Configuration Source Builder I получите следующую ошибку:

"Unable to find appropriate 0 argument constructor for CustomTraceListener"

Когда я пытаюсь найти ошибку, используя базу кода EL5.0, конкретно возникает проблема с построением строки построения для CustomTraceListenerData.

Вот код:

using System;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;

namespace AHCALoggerLibrary
{
[ConfigurationElementType(typeof(CustomTraceListenerData))]
public class ServiceTraceListener : CustomTraceListener
{
    public ServiceTraceListener()
        : base() {}

    public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, object data)
    {
        base.TraceData(eventCache, source, eventType, id, data);
    }

    public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, params object[] data)
    {
        base.TraceData(eventCache, source, eventType, id, data);
    }

    public override void Write(string message)
    {
        throw new NotImplementedException();
    }

    public override void WriteLine(string message)
    {
        throw new NotImplementedException();
    }
}

public class AHCALogger
{
    private static AHCALogger _logger = new AHCALogger();

    private LogWriter _Service = null; 

    public static LogWriter Service { get { return _logger._Service;} }

    private AHCALogger() { }

    public static void Init()
    {
        var builder = new ConfigurationSourceBuilder();

        builder.ConfigureLogging()
               .WithOptions
                 .DoNotRevertImpersonation()
               .LogToCategoryNamed("General")
                .WithOptions.SetAsDefaultCategory()
                    .SendTo.Custom<CustomTraceListener>("ServiceTraceListener")
                   .FormatWith(new FormatterBuilder()
                     .TextFormatterNamed("Text Formatter")
                       .UsingTemplate("Timestamp: {timestamp}...{newline})}"))
                 .SendTo.EventLog("Formatted EventLog TraceListener")
                    .FormatWithSharedFormatter("Text Formatter")
                      .ToLog("Application");

        var configSource = new DictionaryConfigurationSource();
        builder.UpdateConfigurationWithReplace(configSource);
        EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
        _logger._Service = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
    }
}
}

Затем использовать регистратор:

        AHCALogger.Init();
        AHCALogger.Service.Write("hello");

Я подозреваю, что я неправильно его настраиваю, потому что он работает, когда я использую настройки файла конфигурации и вызываю:

LogWriter ahcaLogger = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
ahcaLogger.Write("hello");

Я пытался найти дополнительную информацию о том, как использовать ConfigurationSourceBuilder, но безрезультатно.

Кто-нибудь может мне с этим помочь?


person cyberman    schedule 04.05.2012    source источник


Ответы (1)


Вам нужно заменить

.SendTo.Custom<CustomTraceListener>("ServiceTraceListener") 

с участием

 .SendTo.Custom<ServiceTraceListener>("ServiceTraceListener")

Сообщение об ошибке говорит вам в основном о том, что вы не можете создать экземпляр абстрактного класса. Вам нужно перейти в конкретный класс. В любом случае вам не нужен [ConfigurationElementType (typeof (CustomTraceListenerData))], потому что он не имеет никакого эффекта.

Чтобы передать пользовательские данные конфигурации вашему слушателю трассировки, вы должны знать, что данные хранятся в коллекции атрибутов базового класса TraceListener. Это означает, что вы не можете инициализировать свой слушатель в ctor, кроме первого вызова журнала.

Я немного очистил ваш статический регистратор, чтобы упростить его.

Во время отладки я заметил это раздражающее SynchronizationLockException

«Метод синхронизации объекта был вызван из несинхронизированного блока кода».

которые кажутся ошибкой в Entlib5 фу. Я еще не нашел способа обойти это, кроме как самостоятельно перекомпилировать единство и исправить его.

Вот код работающего логгера с кастомными данными.

using System;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
using System.Linq;
using System.Collections.Specialized;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;

class Program
{
    static void Main(string[] args)
    {
        AHCALogger.Service.Write(new LogEntry() { Message = "Hi" });
    }
}

public static class AHCALogger
{
    static Lazy<LogWriter> _Service = new Lazy<LogWriter>(Init);
    public static LogWriter Service
    {
        get { return _Service.Value; }
    }

    static LogWriter Init()
    {
        var builder = new ConfigurationSourceBuilder();
        var serviceConfig = new NameValueCollection();
        serviceConfig.Add("Key", "data");
        builder.ConfigureLogging()
            .LogToCategoryNamed("General")
            .WithOptions.SetAsDefaultCategory()
            .SendTo.Custom<ServiceTraceListener>("ServiceTraceListener", serviceConfig);

        var configSource = new DictionaryConfigurationSource();
        configSource.Add(LoggingSettings.SectionName, builder.Get(LoggingSettings.SectionName));
        var cont = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);
        return cont.GetInstance<LogWriter>();
    }
}

public class ServiceTraceListener : CustomTraceListener
{
    public ServiceTraceListener() { }
    public override void Write(string message)
    {
        Console.WriteLine("Custom trace Listener Data {0}", 
            String.Join(Environment.NewLine, base.Attributes.Keys.OfType<string>().Select(key => "[" + key + "]: " + base.Attributes[key])));
        Console.WriteLine("message: {0}", message);
    }
    public override void WriteLine(string message) 
    {
        Write(message + Environment.NewLine);
    }
}
person Alois Kraus    schedule 05.05.2012
comment
Большое спасибо! Это помогло. Я не испытываю SynchronizationLockException, поэтому, возможно, он был исправлен в последней версии. - person cyberman; 07.05.2012
comment
Нет это не так. Но вам нужно отключить в параметрах отладки Debug Just My Code, чтобы увидеть все исключения, возникающие в модулях, которые вы не писали. Вы также можете проголосовать за ответ, если сочтете его полезным. - person Alois Kraus; 07.05.2012