重写 ToString() 在抽象类中不起作用(.net-core 3.1)

Ste*_*dis 4 c# serialization .net-core asp.net-core system.text.json

将对象插入字符串时(主要用于日志记录目的),需要显式序列化,否则您将得到:

<ProjectName>.<Class>
Run Code Online (Sandbox Code Playgroud)

或者就我而言

ConsoleApp1.Program+Person
Run Code Online (Sandbox Code Playgroud)

所以我制作了一个非常简单的控制台应用程序作为 PoC 来解决这个问题。

在此 PoC 中,我有一个抽象基类,它仅使用 重写 ToString 方法JsonSerializer,因此我不需要每次想要记录/ConsoleWrite 我的对象时都进行序列化。

    public abstract class BaseModel
    {
        public override string ToString()
        {
            return JsonSerializer.Serialize(this);
        }
    }
Run Code Online (Sandbox Code Playgroud)

这个抽象类应该被我的所有模型继承。这是整个控制台应用程序

        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; }
        }
Run Code Online (Sandbox Code Playgroud)

运行 ConsoleWrites 上面的代码

Hi, {}.
Run Code Online (Sandbox Code Playgroud)

为什么是空的?

当我在抽象方法中放置 Quickwatch 时,this我可以看到属性已正确填充。 在此输入图像描述

为什么会出现这种情况?

ang*_*son 5

您使用的 .NET Core json 序列化器方法是通用的,如下所示:

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

根据设计,它仅在序列化时考虑属性TValue,并且由于您从抽象类调用它,因此this它当然将属于抽象类类型,因此它仅考虑抽象类中的属性。

基本上你的电话被推断为

return JsonSerializer.Serialize<BaseModel>(this);
Run Code Online (Sandbox Code Playgroud)

幸运的是,它很容易修复,只需切换到调用非泛型方法即可:

return JsonSerializer.Serialize(this, GetType());
Run Code Online (Sandbox Code Playgroud)

现在,它使用有关您实际调用它的类型的运行时信息,而不是抽象类,并且应该正确序列化您的后代类型的属性。