Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override ToString() is not working in abstract class (.net-core 3.1)

When interpolating objects into strings (mainly for logging purposes), it needs to be explicitly serialized otherwise what you get is:

<ProjectName>.<Class>

or in my case

ConsoleApp1.Program+Person

So I made a very simple console application as a PoC to tackle this problem.

In this PoC I have an abstract base class that only overrides ToString method with JsonSerializer, so I do not need to serialize every time I want to log/ConsoleWrite my object.

    public abstract class BaseModel
    {
        public override string ToString()
        {
            return JsonSerializer.Serialize(this);
        }
    }

This abstract class is supposed to be inherited by all my models. This is the whole console app

        static async Task Main(string[] args)
        {
            var a = new Person() { Name = "John", Lastname = "Doe" };
            Console.WriteLine($"Hi, {a}.");
            Console.ReadKey();
        }

        public class Person : BaseModel
        {
            public string Name { get; set; }
            public string Lastname { get; set; }
        }

Running the code above ConsoleWrites

Hi, {}.

Why is it empty?

When I put a Quickwatch on this in the abstract method I can see that the properties are populated properly. enter image description here

Why does this happen?

like image 727
Stelios Giakoumidis Avatar asked Oct 20 '25 04:10

Stelios Giakoumidis


1 Answers

The .NET Core json serializer method you used is generic, like this:

public static string Serialize<TValue> (TValue value,
    System.Text.Json.JsonSerializerOptions options = default);

By design, it only considers the properties in TValue when it serializes, and since you called it from your abstract class, with this, which of course will then be of the abstract class type, it only considers properties in the abstract class.

Basically your call is inferred to be

return JsonSerializer.Serialize<BaseModel>(this);

Fortunately, it is easy to fix, simply switch to calling the non-generic method:

return JsonSerializer.Serialize(this, GetType());

Now it uses runtime information about which type you're actually calling it about instead of the abstract class, and should correctly serialize properties from your descendant type.

like image 102
Lasse V. Karlsen Avatar answered Oct 23 '25 00:10

Lasse V. Karlsen