Диспетчеризация по типу против полиморфизма в C#. Бизнес сущности и не бизнес логика

Я хочу выполнить некоторые операции (сохранение базы данных, сериализация json и т. Д.) Над объектом в зависимости от его типа. Полиморфизм - это обычный способ сделать это, но я не хочу добавлять много не-бизнес-логики в мои модели.

Вот простая иерархия типов (это не мои оригинальные типы, а упрощение, чтобы показать проблему):

public abstract class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
}

public class PrintBook : Book
{
    public decimal Weight { get; set; }
    public CoverType CoverType { get; set; }
}

public class Ebook : Book
{
    public EbookType Type { get; set; }
    public bool AutoUpgrade { get; set;}
}

Эти книги создаются на стороне клиента в виде объектов JS, а затем отправляются на сервер в виде JSON (я не могу изменить его структуру) для анализа в список книг:

public List<Book> ParseJson(string json)
{
    /* JSON sample (in JS we have duck typing - the type is determined by its members)
    "books": [
        { "id": 1, "title": "Sample print book", "weight": 50, "coverType": "soft" },
        { "id": 2, "title": "Sample ebook", "type": "pdf", "autoUpgrade": true }
    ]
    */
}

Затем я хочу сохранить этот список в базе данных:

public void SaveBooksToDatabase(List<Book> books)
{
    foreach (var book in books)
    {
        if (book is Ebook)
        {
            Save((Ebook)book);
        }
        else if (book is PrintBook) 
        {
            Save((PrintBook)book);
        }
    }
}

public void Save(Ebook ebook) { /* */ }

public void Save(PrintBook printBook) { /* */ }

Меня не устраивает диспетчеризация типа в методе SaveBooksToDatabase: он нарушает принцип Open-Closed и не очень безопасен при добавлении новых типов.

Но я не хочу добавлять абстрактный метод Save() в иерархию книг, поскольку помимо сохранения существует больше операций, зависящих от типа (например, сериализация json), и это нарушит принцип единой ответственности. Я знаю, что шаблон Visitor можно рассматривать как альтернативное решение, но IMO привнесет более грязный, шаблонный код.

Какой самый лучший и самый элегантный способ обработки таких случаев?

1 ответ

Решение

Я бы разделял объекты, отправленные клиентом, и бизнес-объекты, которые знают, как себя спасти.

У меня был бы один класс, который можно десериализовать из JSON.

Я бы тогда имел несколько бизнес классов Book, PrintBook, EBook, с иерархией наследования. Это будет иметь полиморфный Save методы, среди прочего.

Я бы использовал такой инструмент, как AutoMapper, для сопоставления между объектами передачи данных и бизнес-объектами.

Другие вопросы по тегам