Регистрация зарезервированных слов / символов

#c# #string-interpolation

#c# #строка-интерполяция

Вопрос:

У меня есть *.resx строка, которая выглядит следующим образом:

Failed to deserialize an object of type '{0}' from the following string:{1}{2}

Эта строка используется для регистрации таких ошибок, и в настоящее время оператор протоколирования выглядит следующим образом:

 _logger.LogError(Resources.FailedToDeserialize, typeof(MyType).Name, Environment.NewLine, invalidJsonString);
 

Как вы можете видеть — мне нужно проходить Environment.NewLine каждый раз, чтобы правильно отображать мои журналы для любой ОС.

Мне любопытно, есть ли какие-либо зарезервированные слова / символы интерполяции строк для вставки таких значений?

Например, моя строка может выглядеть так:

Failed to deserialize an object of type '{0}' from the following string:{NewLine}{2}

И мое заявление о регистрации было бы немного проще:

 _logger.LogError(Resources.FailedToDeserialize, typeof(MyType).Name, invalidJsonString);
 

Комментарии:

1. В редакторе ресурсов Visual Studio вы можете использовать Shift Return для вставки разрыва строки внутри значения. Но при этом будет использоваться символ новой строки из вашей текущей ОС, а не ОС, на которой в конечном итоге работает ваше приложение.

2. Кроме того, интерполяция строк — это нечто совершенно иное, чем код, который вы используете в своем вопросе.

3. Одна вещь, которую вы можете сделать, это некоторая форма предварительной обработки при запуске приложения, прочитав файл ресурсов, заменив выбранное вами ключевое слово, т.е. {NewLine} На Environment.NewLine , а затем используйте эту кэшированную строку на протяжении всего срока службы вашего приложения.

4. Итак, у вас есть строка json, которая не прошла десериализацию. Есть ли вероятность появления в этой строке какого-то странного символа, который испортит форматирование используемой библиотеки журналов?

5. @RichardDeeming, думаю, ты прав. Я изменю заголовок.

Ответ №1:

Одна вещь, которую вы можете сделать, это некоторая форма предварительной обработки при запуске приложения, прочитав файл ресурсов, заменив выбранное вами ключевое слово, т.е. {NewLine} На Environment.NewLine , а затем используйте эту кэшированную строку на протяжении всего срока службы вашего приложения.

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

 public static class LoggingMessageTemplates
{
    //Reference your resource here e.g Resource.FailedToDeserialize
    public static string FailedToDeserialize = "Resource.Something {NewLine} Something Else";
    
    public static void FormatMessages() 
    {
        var stringFields = typeof(LoggingMessageTemplates)
            .GetFields()
            .Where(x => x.FieldType == typeof(string));
        
        foreach(var field in stringFields) 
        {
            if (field.GetValue(null) is not string fieldValue)
            {
                throw new InvalidCastException($"Failed to cast field {field.Name} to string.");
            }
            
            field.SetValue(null, fieldValue.Replace("{NewLine}", Environment.NewLine));
        }
    }
}

//On application startup, format the resources to use the Environment.NewLine char of the current system.
LoggingMessageTemplates.FormatMessages();

//When logging, reference the LoggingMessageTemplates class rather than the direct resource.
Console.WriteLine(LoggingMessageTemplates.FailedToDeserialize);

//i.e
_logger.LogError(LoggingMessageTemplates.FailedToDeserialize, typeof(MyType).Name, invalidJsonString);