If I have the following class
public class Customer
{
    public string Name;
}
and then have the following log command in 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);
The log just displays in Seq as
Customer {}
If I change the Name field to a property it works but I would prefer not to do that at this stage. Is there any way around it?
To do this just for the one type (recommended), you can use:
.Destructure.ByTransforming<Customer>(c => new { c.Name })
If you want to include public fields for all types, or those matching some kind of condition, you can plug in a policy to do it:
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;
    }
}
The example scopes this down to look at objects derived from SomeBaseType only.
You can plug it in with:
.Destructure.With<IncludePublicFieldsPolicy>()
(I think it's likely to require some tweaking, but should be a good starting point.)
Thanks to Nicholas Blumhardt for a good starting point. I just have a small tweak.
my class:
public class Dummy
{
    public string Field = "the field";
    public string Property { get; set; } = "the property";
}
log call:
Log.Information("Dummy = {@Dummy}", new Dummy());
IDestructuringPolicy implementation includes both fields and properties:
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;
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With