Легко создать настраиваемую структуру ведения журнала для регистрации ошибок и событий вашего .Net-приложения в плоском файле, базе данных или журнале событий, вам часто может потребоваться регистрировать события или ошибки по мере их возникновения в вашем .Net-приложении. Для этого вы можете воспользоваться одной из многих популярных доступных фреймворков журналирования или спроектировать и разработать свою собственную фреймворк. В этой статье мы увидим, как с легкостью спроектировать и разработать нашу собственную структуру ведения журнала, и рассмотрим шаги по созданию простого средства ведения журнала на C #.

Во-первых, вам необходимо понять цели журнала - различные места, где могут быть зарегистрированы данные. Предположим, мы будем записывать данные в плоские файлы, базу данных и журнал событий. Следующее перечисление определяет цели журнала, которые мы будем использовать в этой простой структуре.

public enum LogTarget
    {
        File, Database, EventLog
    }

Классы регистраторов C #

Следующим шагом является разработка и реализация классов. Мы будем использовать три различных класса, а именно FileLogger, DBLogger и EventLogger, для записи данных в файл, базу данных и журнал событий соответственно. Все эти классы должны наследовать абстрактный базовый класс с именем LogBase. Вот как организованы эти занятия.

public abstract class LogBase
    {
        public abstract void Log(string message);
    }

    public class FileLogger : LogBase
     {
        public string filePath = @”D:\IDGLog.txt”;
        public override void Log(string message)
        {
            using (StreamWriter streamWriter = new StreamWriter(filePath))
            {
                streamWriter.WriteLine(message);
                streamWriter.Close();
            }           
        }
    }

public class DBLogger : LogBase
    {
        string connectionString = string.Empty;
        public override void Log(string message)
        {
            //Code to log data to the database
        }
    }

    public class EventLogger: LogBase
    {
        public override void Log(string message)
        {
            EventLog eventLog = new EventLog(“”);
            eventLog.Source ="IDGEventLog";
            eventLog.WriteEntry(message);
        }
    }

Я оставил DBLogger урок незавершенным. Я предоставлю вам заполнить соответствующий код для регистрации ваших сообщений в базе данных.

Как видите, все три класса - FileLogger, EventLogger и DBLogger - расширяют абстрактный базовый класс LogBase. Абстрактный базовый класс LogBase объявляет абстрактный метод с именем Log(). Метод Log() принимает в качестве параметра строку; эта строка будет записана в файл, базу данных или журнал событий.

Класс C # LogHelper

Теперь давайте создадим вспомогательный класс, который можно использовать для вызова соответствующего регистратора на основе переданного параметра. Этот вспомогательный класс будет использоваться для упрощения вызовов метода Log() в каждом из классов регистратора. Следующий фрагмент кода иллюстрирует этот вспомогательный класс.

public static class LogHelper
    {
        private static LogBase logger = null;
        public static void Log(LogTarget target, string message)
        {
            switch(target)
            {
                case LogTarget.File:
                    logger = new FileLogger();
                    logger.Log(message);
                    break;
                case LogTarget.Database:
                    logger = new DBLogger();
                    logger.Log(message);
                    break;
                case LogTarget.EventLog:
                    logger = new EventLogger();
                    logger.Log(message);
                    break;
                default:
                    return;
            }
        }
    }

Метод Log() класса LogHelper принимает в качестве параметров строку и экземпляр перечисления LogTarget. Затем он использует конструкцию switch: case для определения цели, в которую будет записано текстовое сообщение.

Синхронизация вызовов метода журнала C #

Ой! Мы забыли синхронизировать вызовы соответствующих Log() методов. Для этого нам нужно использовать ключевое слово lock в Log() методе каждого из классов регистратора и включить соответствующий код для синхронизации этих Log() методов. См. Приведенный ниже класс LogBase. Мы включили защищенный член, который будет использоваться для применения блокировки в методе Log() каждого из производных классов. Вот модифицированные версии этих классов.

public abstract class LogBase
    {
        protected readonly object lockObj = new object();
        public abstract void Log(string message);
    }

    public class FileLogger : LogBase
    {
        public string filePath = @”D:\IDGLog.txt”;
        public override void Log(string message)
        {
            lock (lockObj)
            {
                using (StreamWriter streamWriter = new StreamWriter(filePath))
                {
                    streamWriter.WriteLine(message);
                    streamWriter.Close();
                }
            }
        }
    }

    public class EventLogger : LogBase
    {
        public override void Log(string message)
        {
            lock (lockObj)
            {
                EventLog m_EventLog = new EventLog(“”);
                m_EventLog.Source ="IDGEventLog";
                m_EventLog.WriteEntry(message);
            }
        }
    }

    public class DBLogger : LogBase
    {
        string connectionString = string.Empty;
        public override void Log(string message)
        {
            lock (lockObj)
            {
                //Code to log data to the database
            }
        }
    }

Теперь вы можете вызвать метод Log() класса LogHelper и передать цель журнала и текстовое сообщение в журнал в качестве параметров.

class Program
    {
        static void Main(string[] args)
        {
            LogHelper.Log(LogTarget.File, “Hello”);
        }
    }

Если вам когда-нибудь понадобится записать текстовое сообщение в другую цель журнала, вы просто передадите соответствующую цель журнала в качестве параметра методу Log() класса LogHelper.

Есть много способов улучшить эту структуру ведения журналов. Вы можете реализовать асинхронность и очередь, чтобы при поступлении большого количества сообщений регистратор мог обрабатывать эти сообщения асинхронно, не блокируя текущий поток. Вы также можете реализовать уровни критичности сообщений, такие как информационные сообщения, предупреждающие сообщения, сообщения об ошибках и т. Д.