/
aprogrammer
/
serilog
Обзор
Документация
Войти
/
aprogrammer
/
serilog
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
src/Serilog/Events/MessageTemplate.cs
154 строки
6 KB
Igor Stojković
Added ReusableStringWriter (#1771)
09 мар 2023, 08:51
Не верифицирован
09 мар 2023, 08:51
db990d5
Код
Авторство
О чём код?
// Copyright 2013-2015 Serilog Contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. namespace Serilog.Events; /// <summary> /// Represents a message template passed to a log method. The template /// can subsequently render the template in textual form given the list /// of properties. /// </summary> public class MessageTemplate { /// <summary> /// Represents the empty message template. /// </summary> public static MessageTemplate Empty { get; } = new(Enumerable.Empty<MessageTemplateToken>()); /// <summary> /// Construct a message template using manually-defined text and property tokens. /// </summary> /// <param name="tokens">The text and property tokens defining the template.</param> public MessageTemplate(IEnumerable<MessageTemplateToken> tokens) // ReSharper disable PossibleMultipleEnumeration : this(string.Concat(tokens), tokens) // ReSharper enable PossibleMultipleEnumeration { } /// <summary> /// Construct a message template using manually-defined text and property tokens. /// </summary> /// <param name="text">The full text of the template; used by Serilog internally to avoid unneeded /// string concatenation.</param> /// <param name="tokens">The text and property tokens defining the template.</param> /// <exception cref="ArgumentNullException">When <paramref name="text"/> is <code>null</code></exception> /// <exception cref="ArgumentNullException">When <paramref name="tokens"/> is <code>null</code></exception> public MessageTemplate(string text, IEnumerable<MessageTemplateToken> tokens) { Text = Guard.AgainstNull(text); TokenArray = Guard.AgainstNull(tokens).ToArray(); var propertyTokens = GetElementsOfTypeToArray<PropertyToken>(TokenArray); if (propertyTokens.Length != 0) { var allPositional = true; var anyPositional = false; foreach (var propertyToken in propertyTokens) { if (propertyToken.IsPositional) anyPositional = true; else allPositional = false; } if (allPositional) { PositionalProperties = propertyTokens; } else { if (anyPositional) SelfLog.WriteLine("Message template is malformed: {0}", text); NamedProperties = propertyTokens; } } } /// <summary> /// Similar to <see cref="Enumerable.OfType{TResult}"/>, but faster. /// </summary> static TResult[] GetElementsOfTypeToArray<TResult>(MessageTemplateToken[] tokens) where TResult : class { var result = new List<TResult>(tokens.Length / 2); for (var i = 0; i < tokens.Length; i++) { if (tokens[i] is TResult token) { result.Add(token); } } return result.ToArray(); } /// <summary> /// The raw text describing the template. /// </summary> public string Text { get; } /// <summary> /// Render the template as a string. /// </summary> /// <returns>The string representation of the template.</returns> public override string ToString() => Text; /// <summary> /// The tokens parsed from the template. /// </summary> public IEnumerable<MessageTemplateToken> Tokens => TokenArray; internal MessageTemplateToken[] TokenArray { get; } internal PropertyToken[]? NamedProperties { get; } internal PropertyToken[]? PositionalProperties { get; } /// <summary> /// Convert the message template into a textual message, given the /// properties matching the tokens in the message template. /// </summary> /// <param name="properties">Properties matching template tokens.</param> /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param> /// <returns>The message created from the template and properties. If the /// properties are mismatched with the template, the template will be /// returned with incomplete substitution.</returns> /// <exception cref="ArgumentNullException">When <paramref name="properties"/> is <code>null</code></exception> public string Render(IReadOnlyDictionary<string, LogEventPropertyValue> properties, IFormatProvider? formatProvider = null) { using var writer = ReusableStringWriter.GetOrCreate(formatProvider); Render(properties, writer, formatProvider); return writer.ToString(); } /// <summary> /// Convert the message template into a textual message, given the /// properties matching the tokens in the message template. /// </summary> /// <param name="properties">Properties matching template tokens.</param> /// <param name="output">The message created from the template and properties. If the /// properties are mismatched with the template, the template will be /// returned with incomplete substitution.</param> /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param> /// <exception cref="ArgumentNullException">When <paramref name="properties"/> is <code>null</code></exception> /// <exception cref="ArgumentNullException">When <paramref name="output"/> is <code>null</code></exception> public void Render(IReadOnlyDictionary<string, LogEventPropertyValue> properties, TextWriter output, IFormatProvider? formatProvider = null) { Guard.AgainstNull(properties); Guard.AgainstNull(output); MessageTemplateRenderer.Render(this, properties, output, null, formatProvider); } }