Зависимость впрыска и время жизни IDisposable объектов

Я пытаюсь разработать библиотеку, использующую подход для инъекций зависимости (с Ninject), и у меня возникает какая-то путаница из-за моего неправильного дизайна. Итак, мой подход к дизайну

  • Объект parent имеет объект common.
  • Объект parent использует некоторое переменное число объектов child.
  • Все объекты child должны использовать тот же экземпляр объекта common с объектом parent

Вот простая модель моей проблемной области.

interface IParent : IDisposable {
    void Operation();
}
interface ICommon : IDisposable {
    void DoCommonThing();
}
interface IChild1 {
    void DoSomething();
}
interface IChild2 {
    void DoAnotherThing();
}
class Parent : IParent {
    private readonly ICommon _common;
    public Parent(ICommon common) {
        _common = common;
    }
    public void Dispose() {
        _common.Dispose();
    }
    public void Operation() {
        var c1 = ObjectFactory.GetInstance<IChild1>();
        c1.DoSomething();
        var c2 = ObjectFactory.GetInstance<IChild2>();
        c2.DoAnotherThing();
        // number of childs vary, do things until cn
        _common.DoCommonThing();
    }
}
class Common : ICommon {
    private bool _isDisposed;
    public void Dispose() {
        _isDisposed = true;
    }
    public void DoCommonThing() {
        if (_isDisposed) 
            throw new Exception("Common Object is Disposed");
    }
}
class Child1 : IChild1
{
    private readonly ICommon _common;
    public Child1(ICommon common) {
        _common = common;
    }
    public void DoSomething() {
        // Do Something...
        _common.DoCommonThing();
    }
}
class Child2 : IChild2 {
    private readonly ICommon _common;
    public Child2(ICommon common) {
        _common = common;
    }
    public void DoAnotherThing() {
        // Do Another Thing...
        _common.DoCommonThing();
    }
}

Проблема 1

Количество необходимых объектов child меняется. Например, согласно возвращаемому значению c1.DoSomething, я могу или не нуждаюсь в других дочерних объектах. Поэтому я не хочу вводить их через конструктор и просто создавать их, когда они нужны. Но этот подход вызывает нарушение Голливудского принципа.

Вопрос 1

Как это нарушение может быть предотвращено, без ввода дочерних объектов через конструктор?

Проблема 2

Я хочу, чтобы объекты child использовали тот же экземпляр объекта common с их объектом parent. Таким образом, время жизни объекта common должно быть таким же, как и его родитель.

  • Если для ICommon не определено время жизни, тогда все объекты child будут иметь свой собственный экземпляр объекта common.

  • Если время жизни ICommon определено в области Thread или Request, я не могу использовать разные экземпляры объекта parent в той же области Thread или Request. Поскольку каждый объект parent должен использовать свой собственный новый common объект и удалять его.

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

Во-первых, вместо того, чтобы вставлять ICommon в объект parent, объект parent, он сам создает его через ObjectFactory

class Parent : IParent {
    private readonly ICommon _common;
    public Parent() {
        _common = ObjectFactory.GetInstance<ICommon>();
    }
.....

Затем вместо того, чтобы вставлять ICommon в объект child, объект parent устанавливает объект common дочерних объектов.

interface IChild {
    ICommon Common { get; set; }
}
interface IChildN : IChild {
     void DoNthThing();
}
abstract class ChildBase : IChild {
    ICommon IChild.Common { get; set; }
}
class ChildN : IChildN {
     public void DoNthThing() { }
}
class Parent : IParent {
    private readonly ICommon _common;
    public void Operation() {
        var c1 = ObjectFactory.GetInstance<IChild1>();
        c1.Common = _common;
        c1.DoSomething();
        var c2 = ObjectFactory.GetInstance<IChild2>();
        c2.Common = _common;
        c2.DoAnotherThing();
        _common.DoCommonThing();
    }
}

Но это решение снова нарушает принцип Голливуда, и я должен установить свойство Common каждого объекта child.

Вопрос 2

Как объект parent распределяет объект common с объектами child, используя Injection Dependency? (предпочтительно с Ninject)

Вопрос 3

Это немного более общая информация о моей проблеме: как может инъекция зависимостей правильно применяться к этой модели?

ПРИМЕЧАНИЕ: ObjectFactory.GetInstance вызывает Kernel.Get для Ninject

Ответ 1

Вам нужно использовать либо CallScope, либо NamedScope. Они являются частью пакета Ninject.Extensions.NamedScope. Это позволяет вам обменивать общий объект с родителем, чтобы все дочерние запросы получали одинаковый общий.

Относительно создания дочернего объекта. Если вам нужно запросить дочерние объекты в зависимости от некоторого алгоритма, вам необходимо создать экземпляр с помощью factory. Для этого используйте пакет Ninject.Extensions.Factory. Это сохраняет контекст, получая и передавая родительский контекст дочернему запросу и, следовательно, позволяет повторно использовать ваш общий объект также в дочерних элементах, созданных factory.

Итак, в конце вам не понадобится использовать свой собственный объект factory.