覆盖 ToString() 在抽象 class (.net-core 3.1) 中不起作用
Override ToString() is not working in abstract class (.net-core 3.1)
将对象插入字符串时(主要用于日志目的),需要显式序列化,否则得到的是:
<ProjectName>.<Class>
或者在我的情况下
ConsoleApp1.Program+Person
所以我制作了一个非常简单的控制台应用程序作为 PoC 来解决这个问题。
在这个 PoC 中,我有一个抽象基础 class,它只用 JsonSerializer
覆盖 ToString 方法,所以我不需要每次想要 log/ConsoleWrite 我的对象时都进行序列化。
public abstract class BaseModel
{
public override string ToString()
{
return JsonSerializer.Serialize(this);
}
}
这个抽象 class 应该被我所有的模型继承。这是整个控制台应用程序
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; }
}
运行 ConsoleWrites
上面的代码
Hi, {}.
为什么是空的?
当我在抽象方法中将 Quickwatch 放在 this
上时,我可以看到属性已正确填充。
为什么会这样?
将您的序列化代码更改为(假设您使用的是 System.Text.Json
):
public abstract class BaseModel
{
public override string ToString()
{
return JsonSerializer.Serialize(this, this.GetType());
}
}
您在基础 class 中使用通用 JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions)
重载,因此在编译期间通用参数 TValue
被替换为您的 BaseModel
class,其中没有属性,基本上以正在执行 JsonSerializer.Serialize<BaseModel>(this)
调用结束。
您使用的 .NET Core json 序列化程序方法是通用的,如下所示:
public static string Serialize<TValue> (TValue value,
System.Text.Json.JsonSerializerOptions options = default);
根据设计,它在序列化时仅考虑 TValue
中的属性,并且由于您是从摘要 class 中调用它的,使用 this
,这当然会是抽象 class 类型的,它只考虑抽象 class.
中的属性
基本上你的电话被推断为
return JsonSerializer.Serialize<BaseModel>(this);
幸运的是,它很容易修复,只需切换到调用非泛型方法即可:
return JsonSerializer.Serialize(this, GetType());
现在它使用有关您实际调用它的类型的运行时信息,而不是抽象 class,并且应该正确地序列化您的后代类型的属性。
将对象插入字符串时(主要用于日志目的),需要显式序列化,否则得到的是:
<ProjectName>.<Class>
或者在我的情况下
ConsoleApp1.Program+Person
所以我制作了一个非常简单的控制台应用程序作为 PoC 来解决这个问题。
在这个 PoC 中,我有一个抽象基础 class,它只用 JsonSerializer
覆盖 ToString 方法,所以我不需要每次想要 log/ConsoleWrite 我的对象时都进行序列化。
public abstract class BaseModel
{
public override string ToString()
{
return JsonSerializer.Serialize(this);
}
}
这个抽象 class 应该被我所有的模型继承。这是整个控制台应用程序
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; }
}
运行 ConsoleWrites
上面的代码Hi, {}.
为什么是空的?
当我在抽象方法中将 Quickwatch 放在 this
上时,我可以看到属性已正确填充。
为什么会这样?
将您的序列化代码更改为(假设您使用的是 System.Text.Json
):
public abstract class BaseModel
{
public override string ToString()
{
return JsonSerializer.Serialize(this, this.GetType());
}
}
您在基础 class 中使用通用 JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions)
重载,因此在编译期间通用参数 TValue
被替换为您的 BaseModel
class,其中没有属性,基本上以正在执行 JsonSerializer.Serialize<BaseModel>(this)
调用结束。
您使用的 .NET Core json 序列化程序方法是通用的,如下所示:
public static string Serialize<TValue> (TValue value,
System.Text.Json.JsonSerializerOptions options = default);
根据设计,它在序列化时仅考虑 TValue
中的属性,并且由于您是从摘要 class 中调用它的,使用 this
,这当然会是抽象 class 类型的,它只考虑抽象 class.
基本上你的电话被推断为
return JsonSerializer.Serialize<BaseModel>(this);
幸运的是,它很容易修复,只需切换到调用非泛型方法即可:
return JsonSerializer.Serialize(this, GetType());
现在它使用有关您实际调用它的类型的运行时信息,而不是抽象 class,并且应该正确地序列化您的后代类型的属性。