[Boost]::DI 从注入器创建唯一的 shared_ptr 个对象
[Boost]::DI creating unique shared_ptr objects from injector
使用这个示例代码,我希望得到的结果是
button1 和 button2 是两个独立的对象。
#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 = 1
button2->id = 1
而不是预期的:
button1->id = 1
button2->id = 2
从 CommandQueue
单例中删除 di::singleton
生命周期范围也没有解决它。
我知道 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;
}
使用这个示例代码,我希望得到的结果是 button1 和 button2 是两个独立的对象。
#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 = 1
button2->id = 1
而不是预期的:
button1->id = 1
button2->id = 2
从 CommandQueue
单例中删除 di::singleton
生命周期范围也没有解决它。
我知道 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;
}