Вызов дочернего конструктора путем приведения (ChildClass) parentObject; отслеживать изменения - PullRequest
2 голосов
/ 23 апреля 2010

Для отслеживания ревизий класса Page у меня есть класс PageRevision, который наследуется от Page и добавляет идентификатор ревизии (Guid RevisionID;).

Если возможно, как я должен кастоватьсуществующий объект Page в PageRevision и убедиться, что конструктор PageRevision вызывается для создания нового идентификатора ревизии?

Я мог бы иметь конструктор PageRevision(Page page), который генерирует Guid и копирует все страницы.атрибутов, но я хочу автоматизировать его, особенно если класс Page имеет много атрибутов (а позже я добавлю один и забуду изменить конструктор копирования).

Желаемое использование

Page page = new Page(123, "Page Title", "Page Body"); // where 123 is page ID
PageRevision revision = (PageRevision)page;
// now revision.RevisionID should be a new Guid.

Page, PageRevision классы:

public class Page
{
    public int ID { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
}

public class PageRevision : Page
{
    public Guid RevisionID { get; set; }

    public PageRevision()
    {
        this.RevisionID = Guid.NewGuid();
    }
}

Редактирование на основе обратной связи:

Помимо очевидной на сегодня проблемы с кастингом (Horse)Animal;, Джон Скит рекомендует составную версию:

public class PageRevision : Page
{
    private readonly Page page;
    private readonly Guid id;
    public Guid RevisionID { get { return id; } }
    public Page Page { get { return page; } }

    public PageRevision(Page page)
    {
        this.id = Guid.NewGuid();
        this.page = page;
    }
}

Тем не менее, это сильно отличается от моей модели данных, и я хотел бы, чтобы эти две модели были максимально похожими.В моей базе данных таблица PageRevisions имеет те же столбцы, что и таблица Pages, за исключением дополнительного столбца RevisionID.Это просто для версии с триггером базы данных.

  • В свете этого комбинированного подхода, имеет ли смысл иметь PageRevisions для хранения всех данных страницы: a RevisionID, Title и Body, тогда как в таблице Pages хранятся только URL Slug и RevisionID, которые относятся к таблице PageRevisions?

Ответы [ 4 ]

5 голосов
/ 23 апреля 2010

Почему бы не сделать ваш класс PageRevision составным вместо наследования?

public class PageRevision : Page
{
    private readonly Page page;
    private readonly Guid id;
    public Guid RevisionID { get { return id; } }
    public Page Page { get { return page; } }

    public PageRevision(Page page)
    {
        this.id = Guid.NewGuid();
        this.page = page;
    }
}
1 голос
/ 23 апреля 2010

Конструктор PageRevision ВСЕГДА вызывается независимо от того, приведен ли класс к PageRevision или нет.Так что это вообще не сработает.

Вероятно, имеет смысл сказать, почему вы хотите это сделать, потому что вы, вероятно, делаете это по причинам, которые решаются другими способами.

1 голос
/ 23 апреля 2010

Вы не можете.

Лошадь - это животное, но не каждое животное - это лошадь.

Так что лошадь => животное возможно, а животное => лошадь нет. И вы пытаетесь бросить свое животное в лошадь.

1 голос
/ 23 апреля 2010

Во время приведения не вызывается конструктор, потому что объект уже создан.

Хотя ваше приведение не будет выполнено во время выполнения, причина Page не может быть приведена к PageRevision (возможен другой способ)

В вашем случае я бы добавил RevisionId в ваш базовый класс Page.Если вы создаете объект Page, он может быть создан с помощью Guid.Empty.Производные классы могут устанавливать RevisionId, используя конструктор вашего базового класса Page.

public class Page {

    public Page() {
        RevisionId = Guid.Empty;
    }

    protected Page(Guid revisionId) {
        RevisionId = revisionId;
    }

    public Guid RevisionId {
        get;
        private set;
    }
}

public class PageRevision : Page {

    public PageRevision()
        : base(Guid.NewGuid()) {

    }
}
...