boost-ext / di

C++14 Dependency Injection Library
https://boost-ext.github.io/di
1.16k stars 140 forks source link

Manually get a dependency in a managed class #453

Closed popov-aa closed 4 years ago

popov-aa commented 4 years ago

How can I manually get a dependency in a managed class? Like this:

#include <Hypodermic/Container.h>
#include <memory>

class C {
public:
    explicit C(std::shared_ptr<Hypodermic::Container> container) {
        m_container = container;
    }

    virtual void onButtonClicked() {
        ui->layout->addWidget( m_container->resolve<UserWidget>() );
    }

private:
    std::shared_ptr<Hypodermic::Container> m_container;
};
krzysztof-jusiak commented 4 years ago

Thanks, @popov-aa for posting the question.

You can do it wit [boost].di and type-erased version of the injector. You can find an example here:

However, I would not recommend doing it as it's a Service Locator pattern (passing the container around) which is often considered as an anti-pattern and may bite you in the long term. You can find some more info about it in the following video.

Anyhow, from DI perspective a better approach would be to use something similar to a lazy provider if you need a new instance each time or just inject a desired type itself 🤔 Examples here:

popov-aa commented 4 years ago

Thank you for your answer. Do you have forum or something where I may ask newbie questions?

I created test project for learning boost-di. It's look awesome. But I got errors on some cases. https://github.com/popov-aa/QtBoostDIExample/tree/errors I have dialogs AboutDialog and ConnectionDialog. I want get it from factory with parameter "parent". Parent - it's reference to QWidget. When I register factory in injector like this

boost::di::bind<boost::di::extension::ifactory<AboutDialog, QWidget*>>().to(boost::di::extension::factory<AboutDialog> {}),

I got error:

/home/popov/Projects/C++/Tests/QtBoostDIExample/QtBoostDIExample/boost-di/include/boost/di.hpp:1287: incomplete type ‘boost::di::v1_1_0::aux::is_constructible<QWidget, boost::di::v1_1_0::core::any_type<QWidget, boost::di::v1_1_0::core::injector<boost::di::v1_1_0::config, boost::di::v1_1_0::core::pool<boost::di::v1_1_0::aux::type_list<> >, boost::di::v1_1_0::detail::<lambda(auto:1)> [with auto:1 = boost::di::v1_1_0::core::injector<boost::di::v1_1_0::config, boost::di::v1_1_0::core::pool<boost::di::v1_1_0::aux::type_list<> >, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::deduce, PermissionsContainer, PermissionsContainer, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::deduce, PermissionsModel, PermissionsModel, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::deduce, ConnectionService, ConnectionService, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::instance, boost::di::v1_1_0::extension::ifactory<AboutDialog, QWidget*>, boost::di::v1_1_0::extension::factory<AboutDialog>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::instance, boost::di::v1_1_0::extension::ifactory<UserWidget, QString, QWidget*>, boost::di::v1_1_0::extension::factory<UserWidget>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::instance, boost::di::v1_1_0::extension::ifactory<ConnectionDialog>, boost::di::v1_1_0::extension::factory<ConnectionDialog>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::deduce, MainWindow, MainWindow, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none> >]::i, boost::di::v1_1_0::core::dependency<boost::di::v1_1_0::scopes::instance, QWidget*, QWidget*, boost::di::v1_1_0::no_name, boost::di::v1_1_0::core::override, boost::di::v1_1_0::core::none> >, boost::di::v1_1_0::core::with_error>, boost::di::v1_1_0::core::any_type<QWidget, boost::di::v1_1_0::core::injector<boost::di::v1_1_0::config, boost::di::v1_1_0::core::pool<boost::di::v1_1_0::aux::type_list<> >, boost::di::v1_1_0::detail::<lambda(auto:1)> [with auto:1 = boost::di::v1_1_0::core::injector<boost::di::v1_1_0::config, boost::di::v1_1_0::core::pool<boost::di::v1_1_0::aux::type_list<> >, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::deduce, PermissionsContainer, PermissionsContainer, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::deduce, PermissionsModel, PermissionsModel, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::deduce, ConnectionService, ConnectionService, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::instance, boost::di::v1_1_0::extension::ifactory<AboutDialog, QWidget*>, boost::di::v1_1_0::extension::factory<AboutDialog>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::instance, boost::di::v1_1_0::extension::ifactory<UserWidget, QString, QWidget*>, boost::di::v1_1_0::extension::factory<UserWidget>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::instance, boost::di::v1_1_0::extension::ifactory<ConnectionDialog>, boost::di::v1_1_0::extension::factory<ConnectionDialog>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, boost::di::v1_1_0::extension::dependency_proxy<boost::di::v1_1_0::scopes::deduce, MainWindow, MainWindow, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none> >]::i, boost::di::v1_1_0::core::dependency<boost::di::v1_1_0::scopes::instance, QWidget*, QWidget*, boost::di::v1_1_0::no_name, boost::di::v1_1_0::core::override, boost::di::v1_1_0::core::none> >, boost::di::v1_1_0::core::with_error> >’ used in nested name specifier
 1287 |   static constexpr auto value = aux::is_constructible<T, TArgs...>::value;
      |                         ^~~~~
class AboutDialog : public QDialog {
    Q_OBJECT

public:
    explicit AboutDialog(QWidget* parent = nullptr);
    ~AboutDialog();

private:
    Ui::AboutDialog* ui;
};
    const boost::di::extension::ifactory<AboutDialog, QWidget*>& m_aboutDialog;
...
    auto dialog = m_aboutDialog.create(this);
    dialog->exec();

Where I made mistake?