Обновить MDC в методе - PullRequest
       9

Обновить MDC в методе

0 голосов
/ 06 ноября 2018

Допустим, у вас есть код, использующий сопоставленный контекст диагностики с использованием:

public string TransformTruTopsFABExport(string xmlFile) {
var xml = String.Empty;

using (NestedDiagnosticsContext.Push(Guid.NewGuid()))
using (MappedDiagnosticsLogicalContext.SetScoped("xmlFile", xmlFile))
using (MappedDiagnosticsLogicalContext.SetScoped("xml", xml))
{
    try
    {
        Logger.Info("Transformation started.");
        xml = Decorated.TransformTruTopsFABExport(xmlFile);
        MappedDiagnosticsLogicalContext.Set("xml", xml); // Try to remove it
        Logger.Debug("Transformation done.");
        return xml;
    }
    finally
    {
        xml = null;
    }
}

}

Как я могу обновить переменную "xml" и автоматически зеркалировать обновление в MDC, не устанавливая его из нового? После использования он будет автоматически удален из стека, но выглядит как двойной код. Могу ли я использовать что-то вроде указателей c?

Изменить: Прежде чем вы спросите, я уже пытался использовать DataClass, как это:

    class Dataclass
{
    public string xml { get; set; }

    public override string ToString()
    {
        return xml;
    }
}

class Logicclass
{
    Logger logger = LogManager.GetLogger("Logicclass");

    public void MyMethod()
    {
        var dc = new Dataclass();

        using (MappedDiagnosticsLogicalContext.SetScoped("xml", dc))
        {
            try
            {
                logger.Info("before XML");
                dc.xml = "xmlcode";
                logger.Info("after XML");
            }
            catch (Exception ex)
            {
                logger.Error(ex, "ow noos!");
                throw;
            }
        }

        logger.Info("after using");
    }
}

И да, это обновит его Но это не тот ответ, который я ищу.

Edit: Самое простое решение для переменных является неизменным, и ссылка не будет работать, для этого используется StringBuilder. Обновление объекта StringBuilder простое, и вот рабочее решение с использованием ссылки на объект объекта StringBuilder с MDLC (магия очищает его перед добавлением содержимого):

public void MyMethod()
{
    StringBuilder xml = new StringBuilder();
    StringBuilder numbers = new StringBuilder();
    StringBuilder booleans = new StringBuilder();

    using (NestedDiagnosticsContext.Push(Guid.NewGuid()))
    using (MappedDiagnosticsLogicalContext.SetScoped("xml", xml))
    using (MappedDiagnosticsLogicalContext.SetScoped("numbers", numbers))
    using (MappedDiagnosticsLogicalContext.SetScoped("booleans", booleans)) 
    {
        try {

            logger.Info("Before XML change");

            xml.Clear().Append("<?xml version=\"1.0\" encoding=\"utf-8\"?>..");
            numbers.Clear().Append(20);
            logger.Info("After XML change");
            booleans.Clear().Append(true);
            logger.Info("After Boolean change");
            numbers.Clear().Append(100);
            logger.Info("After number change");
            xml.Clear().Append("no xml anymore");
            logger.Info("After XML change");
        }
        catch (Exception ex)
        {
            logger.Error(ex, "ow noos!");
            throw;
        }
    }
    logger.Info("After using");
}

Конечно, я был бы непрактичным для возвращаемых значений, потому что вам пришлось бы преобразовывать его обратно, но в большинстве случаев я являюсь хорошим решением и немного более читабельным, чем повторная установка MDLC.

С наилучшими пожеланиями Lord_Pinhead

1 Ответ

0 голосов
/ 08 ноября 2018

MappedDiagnosticsLogicalContext.SetScoped не восстанавливает первоначальное значение при утилизации. Он просто удаляет активное значение при утилизации.

Строковые объекты NET Framework являются неизменяемыми и не могут быть изменены. Вы можете рассмотреть возможность использования StringBuilder (будет вести себя как ваш DataClass).

...