簡體   English   中英

IDisposable對象的依賴注入和生命周期

[英]Dependency injection and life time of IDisposable objects

我正在嘗試使用依賴注入方法(使用Ninject)開發一個庫,我可能會因為我的設計不正確而產生某種混淆。 總之,我的設計方法是

  1. parent對象具有common對象。
  2. parent對象使用一些可變數量的child對象。
  3. 所有child對象都應該使用與parent對象完全相同的common對象實例

這是我的問題域的簡單模型。

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對象與parent對象使用相同的common對象實例。 因此, common對象的生命時間應與其父對象相同。

  1. 如果沒有為ICommon定義生命時間,則所有child對象都將擁有自己的common對象實例。

  2. 如果在Thread或Request范圍中定義了ICommon的生命周期,那么我不能在同一個Thread或Request范圍中使用parent對象的不同實例。 因為每個parent對象都應該使用自己的全新common對象並進行處理。

所以我無法使用我所知道的終身范圍選項解決它。 我為第二個問題制作了另一個解決方案,但它使代碼變得更糟。

首先,不是將ICommon注入parent對象,而是通過ObjectFactory自己創建parent對象

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

然后, parent對象不是將ICommon注入child對象,而是設置子對象的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();
    }
}

但是這個解決方案再次違反了好萊塢原則,我必須設置每個child對象的Common屬性。

問題2

parent對象如何使用依賴注入將其common對象分發給child對象? (最好是Ninject)

問題3

這對我的問題更為籠統:Dependency Injection如何正確應用於此模型?

注意: ObjectFactory.GetInstance調用Ninject的Kernel.Get

您需要使用任一CallScopeNamedScope 這些是Ninject.Extensions.NamedScope包的一部分。 這允許您將公共對象的范圍限定為父對象,以便所有子請求都接收相同的公共對象。

關於子對象創建。 如果您必須根據某些算法請求子對象,則需要使用工廠對其進行實例化。 使用Ninject.Extensions.Factory包來實現此目的。 這樣做了一個上下文保留get並將父上下文傳遞給子請求,因此允許在工廠創建的子節點中重用您的公共對象。

所以最終不需要使用自己的對象工廠。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM