2017-10-19 85 views
2

以此示例代碼爲例,我希望 button1和button2是兩個單獨的對象。[Boost] :: DI從注入器創建唯一的shared_ptr對象

#include <iostream> 
#include <memory> 
#include "di.hpp" 
namespace di = boost::di; 

struct CommandQueue { 
    void addCommand() {} 
}; 

struct Control { 
    Control(CommandQueue &cq) : cq(cq) { 
     static int sid{}; 
     id = ++sid; 
    } 

    CommandQueue& cq; 
    int id{}; 
}; 

int main() { 

    auto injector = di::make_injector(di::bind<CommandQueue>().in(di::singleton)); 

    auto button1 = injector.create<std::shared_ptr<Control>>(); 
    auto button2 = injector.create<std::shared_ptr<Control>>(); 

    std::cout << "button1->id = " << button1->id << std::endl; 
    std::cout << "button2->id = " << button2->id << std::endl; 

    return 0; 
} 

電流輸出是:

button1-> ID =

button2-> ID =

相反的意圖:

button1-> ID =

button2-> ID =

卸下從CommandQueue單的di::singleton壽命範圍也不能解決問題。 我知道shared_ptr的生命週期默認情況下是單例,但我認爲它被引用到注入的依賴關係中,而不是用create創建的實際對象。

+0

什麼是addCommand' – sehe

+0

的'相關性這只是一個佔位符,以證明使用CommandQueue作爲單身,但即使沒有這些代碼仍然創造1對象而不是2 – Dado

回答

1

實際上最簡單的事情可能是

auto button1 = injector.create<Control>(); 
auto button2 = injector.create<Control>(); 

std::cout << "button1.id = " << button1.id() << std::endl; 
std::cout << "button2.id = " << button2.id() << std::endl; 

打印

button1.id = 1 
button2.id = 2 

如果必須具有共享指針,接下來最簡單的事情將是

auto button1 = std::make_shared<Control>(injector.create<Control>()); 
auto button2 = std::make_shared<Control>(injector.create<Control>()); 

std::cout << "button1->id = " << button1->id() << std::endl; 
std::cout << "button2->id = " << button2->id() << std::endl; 

概念你想要一個控制工廠,而不是控制。所以,你應該考慮從依賴容器創建一個工廠:

#include <boost/di.hpp> 
#include <iostream> 
#include <memory> 
namespace di = boost::di; 

struct CommandQueue { 
    void addCommand() {} 
}; 

struct Control { 
    Control(CommandQueue &cq) : _cq(cq), _id(idgen()) { } 

    int id() const { return _id; } 

    struct Factory { 
     Factory(CommandQueue& cq) : _cq(cq) {} 
     CommandQueue& _cq; 

     template <typename... Args> 
     auto operator()(Args&&... args) const { 
      return std::make_shared<Control>(_cq, std::forward<Args>(args)...); 
     } 
    }; 
    private: 
    static int idgen() { static int sid{}; return ++sid; } 
    CommandQueue &_cq; 
    int _id{}; 
}; 

int main() { 
    auto injector = di::make_injector(di::bind<CommandQueue>().in(di::singleton)); 

    auto factory = injector.create<Control::Factory>(); 
    auto button1 = factory(); 
    auto button2 = factory(); 

    std::cout << "button1->id = " << button1->id() << std::endl; 
    std::cout << "button2->id = " << button2->id() << std::endl; 
} 
+0

謝謝,我不想在我們的lib中打破OCP,所以將shared_ptr轉換爲對象並不是一個好的選擇,我已經考慮過像您在第二個示例中所建議的「裸」make_shared,但是我不確定這是否是DI的最佳實踐,最後是的,我已經將真正的代碼封裝到工廠中了,但是我仍然想知道如果使用DI,我會在創建的左側調用make_shared,我不想這樣做,以避免深層複製,並不得不寫迭代ctor。基本上我只是想重新確保我沒有做任何錯事:) – Dado

+0

你剛剛告訴我,我浪費了我的時間下載增強DI,閱讀文檔(和代碼,轉瞬即逝),並提出了建議? – sehe

+0

嗯不,你爲什麼會這麼想?我想詳細說明我的思維過程,我不確定是否要編輯原始問題以附加信息或答覆作爲註釋 – Dado

相關問題