2017-10-19 12 views
2

En prenant cet exemple de code, je voudrais avoir comme résultat que button1 et button2 sont deux objets distincts.[Boost] :: DI créant des objets shared_ptr uniques à partir de l'injecteur

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

Le courant de sortie est la suivante:

button1-> id =

button2-> id =

Au lieu de la destinée:

button1-> id =

button2-> id =

Retrait du périmètre de vie di::singleton de CommandQueue singleton ne fixe pas aussi. Je sais que la portée à vie d'un shared_ptr est un singleton par défaut mais je pensais que c'était la dépendance injectée et non l'objet créé avec create.

+0

Quelle est la pertinence de 'addCommand' – sehe

+0

Il est juste un espace réservé pour justifier l'utilisation de CommandQueue comme singleton mais même sans que le code serait toujours créer 1 objet au lieu de 2 – Dado

Répondre

1

En effet, la chose la plus simple pourrait être

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; 

Prints

button1.id = 1 
button2.id = 2 

Si vous doit avoir pointeurs partagés, la prochaine chose la plus simple serait

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; 

Conceptuellement vous voulez une usine de contrôle, pas un contrôle. Donc, vous devriez envisager de créer une usine à partir du conteneur de dépendance:

#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

Merci, je ne voulais pas casser l'OCP dans notre lib donc la conversion du shared_ptr en un objet n'était pas une bonne option, j'ai considéré le make_shared "nu" comme vous l'avez suggéré dans votre deuxième exemple mais Je n'étais pas sûr que c'était la meilleure pratique avec DI, enfin oui j'ai déjà encapsulé le vrai code dans une usine mais encore je me demandais si avec DI je m'absenterais d'appeler make_shared sur le côté gauche de la création, qui Je ne voulais pas faire pour éviter une copie en profondeur et avoir à wr ite une copie ctor. Essentiellement, je voulais juste re-assurance que je ne faisais pas terriblement mal :) – Dado

+0

Avez-vous juste me dire très minutieusement que j'ai perdu mon temps à télécharger boost DI, à lire les docs (et le code, fugitivement) et à venir avec des suggestions? – sehe

+0

Hmm non pourquoi penses-tu cela? Je voulais élaborer mon processus de pensée et je n'étais pas sûr de vouloir éditer la question originale avec des informations supplémentaires ou de répondre comme un commentaire. – Dado