Serilog сериализует поля

Если у меня есть следующий класс

public class Customer
{
    public string Name;
}

а затем иметь следующую команду журнала в Serilog

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.Seq("http://localhost:5341")
    .CreateLogger();

var item = new Customer();
item.Name = "John";
Serilog.Log.Information("Customer {@item}", item);

Журнал просто отображается в Seq как

Customer {}

Если я изменю поле "Имя" на свойство, оно будет работать, но я бы предпочел не делать этого на этом этапе. Есть ли способ обойти это?

1 ответ

Решение

Чтобы сделать это только для одного типа (рекомендуется), вы можете использовать:

.Destructure.ByTransforming<Customer>(c => new { c.Name })

Если вы хотите включить открытые поля для всех типов или те, которые соответствуют каким-либо условиям, вы можете подключить политику, чтобы сделать это:

class IncludePublicFieldsPolicy : IDestructuringPolicy
{
    public bool TryDestructure(
        object value,
        ILogEventPropertyValueFactory propertyValueFactory,
        out LogEventPropertyValue result)
    {
        if (!(value is SomeBaseType))
        {
            result = null;
            return false;
        }

        var fieldsWithValues = value.GetType().GetTypeInfo().DeclaredFields
            .Where(f => f.IsPublic)
            .Select(f => new LogEventProperty(f.Name,
               propertyValueFactory.CreatePropertyValue(f.GetValue(value))));

        result = new StructureValue(fieldsWithValues);
        return true;
    }
}

Пример ограничивает это, чтобы посмотреть на объекты, полученные из SomeBaseType только.

Вы можете подключить его с помощью:

.Destructure.With<IncludePublicFieldsPolicy>()

(Я думаю, что это, вероятно, потребует некоторой настройки, но должно быть хорошей отправной точкой.)

Спасибо Николасу Блюмхардту за хорошую отправную точку. Просто у меня небольшая поправка.

мои занятия:

public class Dummy
{
    public string Field = "the field";
    public string Property { get; set; } = "the property";
}

журнал вызовов:

Log.Information("Dummy = {@Dummy}", new Dummy());

Реализация IDestructuringPolicy включает как поля, так и свойства:

internal class IncludePublicFieldsPolicy : IDestructuringPolicy
{
    public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result)
    {
        var typeInfo = value.GetType().GetTypeInfo();

        var fieldsWithValues = typeInfo
            .DeclaredFields
            .Where(f => f.IsPublic)
            .Select(f =>
            {
                var val = f.GetValue(value);
                var propval = propertyValueFactory.CreatePropertyValue(val);
                var ret = new LogEventProperty(f.Name, propval);
                return ret;
            })
        ;

        var propertiesWithValues = typeInfo
            .DeclaredProperties
            .Where(f => f.CanRead)
            .Select(f =>
            {
                var val = f.GetValue(value);
                var propval = propertyValueFactory.CreatePropertyValue(val);
                var ret = new LogEventProperty(f.Name, propval);
                return ret;
            })
        ;

        result = new StructureValue(fieldsWithValues.Union(propertiesWithValues));
        return true;
    }
}
Другие вопросы по тегам