[提升]::D我从喷油器创建独特的shared_ptr对象

[Boost]::DI creating unique shared_ptr objects from injector

本文关键字:shared 对象 ptr 创建 提升      更新时间:2023-10-16

以此示例代码为例,我希望得到的结果是按钮 1 和按钮 2 是两个单独的对象。

#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;
}

当前输出为:

按钮1->ID = 1

按钮2->ID = 1

而不是预期的:

按钮1->ID = 1

按钮2->ID = 2

从单一实例中删除di::singleton生存期范围CommandQueue也不能修复它。我知道shared_ptr的生存范围默认是单例,但我认为这是指注入的依赖项,而不是使用 create 创建的实际对象。

事实上,最简单的事情可能是

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;
}