Коллекции производных детских классов - PullRequest
2 голосов
/ 21 ноября 2010

Существует ли принятый метод добавления объектов, возможно производных от объекта, в коллекцию без , позволяющих создавать экземпляры базовых или производных объектов самостоятельно?Я думаю, что это почти противоречие в терминах.

О единственном методе, который мне удалось придумать, - это добавить в родительскую коллекцию базовую реализацию дочернего элемента, например:*

Это заставляет дочерний объект всегда создаваться с родительским объектом, но кажется довольно грязной реализацией, чтобы добавить дочерний класс в родительскую коллекцию из дочернего.Я знаю, что могу передать переменную Type-type методу, и это может быть путь, но я не уверен, как создать / привести к переданному типу.


Обновление:Я играю с кодом, который выглядит следующим образом как возможный универсальный метод ChildCollection.Add, на случай, если это даст кому-то лучшее представление о том, что я хочу ... посмотрим, будет ли он работать в долгосрочной перспективе:

// Currently testing directly in Parent class;
// can later be moved/modified for Parent's ChildCollection class.
public Child AddTest(string info, Type derivedType)
{
    ConstructorInfo ci = derivedType.GetConstructor(new Type[] { typeof(Parent) });
    Child myBaby = (Child) ci.Invoke(new Object[] { this });
    myBaby.Initialize(info);
    return myBaby;
}

Это можно затем вызвать с помощью кода, подобного:

Child newChild = Parent.AddTest("Hello World", typeof(DerivedChild));

Ответы [ 3 ]

1 голос
/ 21 ноября 2010

Ограничение состоит в том, что дочерний объект не должен существовать без родителя. Как насчет предоставления свойства типа «IsAttached» или «Parent» и использования внутренних методов для присоединения дочерних объектов к родительскому объекту? Тогда дочерние объекты могут быть созданы в любом месте вашей кодовой базы, но не будут действительными дочерними объектами, пока не будут присоединены.

- internal Attach(parent) 
- internal Detach() 
- public IsAttached

Затем родительская коллекция может реализовывать методы для добавления дочерних объектов и выполнения некоторой проверки. Я думаю в духе форм и элементов управления.

Collection.Add(child) 
{
    // throw error if the child is not the right type
    child.Attach(this)
    base.add(child)    
} 
1 голос
/ 22 ноября 2010

В конечном итоге я выбрал код, очень похожий на тот, который я опубликовал в своем обновлении.Я публикую это здесь, так как считаю, что это полезный метод для фабрики универсальных объектов или для ограниченной (в данном случае, ограниченный теми, которые являются производными от класса Child).

Основная идея заключается в том, чточтобы создать собственную коллекцию, затем используйте метод Add (или, возможно, я должен назвать его Create?), чтобы создать экземпляр объекта и правильно обработать любую переопределенную инициализацию в производной от Child.

Вот скелет кода, который я закончилс:

// Use standard Child
public Child Add(string initInfo)
{
    Child newChild = new Child(this.Parent);
    // There's actually a bit more coding before Initialize()
    // in the real thing, but nothing relevant to the example.
    newChild.Initialize(initInfo);
    List.Add(newChild);
    return newChild;
}

// Overload for derived Child.
public Child Add(Type childDerivative, string initInfo)
{
    if (!childDerivative.IsSubclassOf(typeof(Child)))
        throw new ArgumentException("Not a subclass of Child.");
    ConstructorInfo ci = childDerivative.GetConstructor(
        BindingFlags.Instance |
        BindingFlags.Public | BindingFlags.NonPublic |
        BindingFlags.FlattenHierarchy |
        BindingFlags.ExactBinding, 
        null, new Type[] { typeof(Parent) }, null);
    if (ci == null)
        throw new InvalidOperationException("Failed to find proper constructor.");
    newChild = (Child)ci.Invoke(new Object[] { this.Parent });
    newChild.Initialize(initInfo);
    List.Add(newChild);
    return newChild;
}

Поскольку это может не охватывать все возможные производные дочерние элементы, которые клиентское приложение может захотеть создать (особенно если они добавляют свои собственные параметры в конструктор), я думаю, чтовероятно, также предоставляют метод Add (Child child) с предупреждением о том, что если пользователь создает экземпляр объекта Child со стандартным «new Child (Parent)», он также отвечает за выполнение всех стандартных шагов инициализации ожидаемым образом..

0 голосов
/ 21 ноября 2010

Если вы серьезно относились к тому, что вам не нужно иметь возможность СОЗДАТЬ экземпляры родительского типа, просто сделайте его конструктор защищенным или объявите его абстрактным.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...