Переопределение ToString () не работает в абстрактном классе (. net -core 3.1) - PullRequest
2 голосов
/ 29 мая 2020

При интерполяции объектов в строки (в основном для целей ведения журнала) его необходимо явно сериализовать, иначе вы получите:

<ProjectName>.<Class>

или в моем случае

ConsoleApp1.Program+Person

Итак Для решения этой проблемы я сделал очень простое консольное приложение Po C.

В этом Po C у меня есть абстрактный базовый класс, который заменяет только метод ToString с помощью JsonSerializer, поэтому мне не нужно сериализовать каждый раз, когда я хочу регистрировать / ConsoleWrite мой объект.

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

Этот абстрактный класс должен быть унаследован всеми моими моделями. Это все консольное приложение

        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 в абстрактный метод. Я вижу, что свойства заполнены правильно. enter image description here

Почему это происходит?

Ответы [ 2 ]

4 голосов
/ 29 мая 2020

Используемый вами метод сериализатора. NET Core json является generi c, например:

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

По дизайну он учитывает свойства в TValue только при сериализации, и поскольку вы вызвали его из своего абстрактного класса с помощью this, который, конечно, будет иметь тип абстрактного класса, он рассматривает только свойства в абстрактном классе.

В основном ваш вызов считается

return JsonSerializer.Serialize<BaseModel>(this);

К счастью, это легко исправить, просто переключитесь на вызов метода non-generi c:

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

Теперь он использует информацию времени выполнения о том, какой тип вы на самом деле вызывая его вместо абстрактного класса, и он должен правильно сериализовать свойства из вашего потомка.

3 голосов
/ 29 мая 2020

Измените код сериализации на (при условии, что вы используете System.Text.Json):

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

Вы используете перегрузку generi c JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions) в базовом классе, поэтому во время compilation generi c параметр TValue заменяется вашим BaseModel классом, который не имеет свойств, в основном заканчивая выполняемым вызовом JsonSerializer.Serialize<BaseModel>(this).

...