Closed lehajam closed 5 years ago
I'd like to know the same, since I also want to inject multiple instances of the same class with different constructor parameters.
If I understood it correctly, a first step would probably be to move from references (since those are automatically deduced to be a singleton) to something like a pointer. See here.
I've managed to create two objects with separate injectors, is the same also possible with a single injector? What would the injector call look like? Thanks in advance!
class Impl : public Interface
{
public:
Impl(int a, float b) :
_a(a),
_b(b) {}
virtual void init(){};
int _a;
float _b;
};
class User1
{
public:
User1(Interface* in) :
user(in) {}
Interface* user;
};
class User2
{
public:
User2(Interface* in) :
user(in) {}
Interface* user;
};
int main()
{
const auto inj = [] {
return ::di::make_injector(
di::bind<int>().to(1),
di::bind<float>().to(2.0f),
di::bind<Interface>().to<Impl>()
);
};
const auto inj2 = [] {
return ::di::make_injector(
di::bind<int>().to(2),
di::bind<float>().to(3.0f),
di::bind<Interface>().to<Impl>()
);
};
auto test = inj().create<User1>();
auto test2 = inj2().create<User2>();
}
Hi guys.
Did you try annotations aka named arguments? The problem is if you want to have 2 different argument with the same type you need a way to distinguish them. The simplest way is to give them names. It also could be contextual binding. However, it is not supported yet. @krzysztof-jusiak is working on it at the moment.
Hi Kanstantsin,
Thanks for taking the time to reply, my understanding is that for multiple instances of the same class, named arguments would lead to the same issue and I think I ended up with a bound_more_than_once error. I can see why my use case is not working, maybe its just a wrong use case for DI as i'm trying to inject instances of a given class rather than implementations of a given interface but I was hoping for some magic. You know the saying, the more we get the more we want :)
So far it seems to me the solution would be to inject the instances readily built / initialized rather than relying on DI to do it.
Lehajam
Played around with the factory extension and got it working to suit my needs. I will probably stick with this, @lehajam maybe this can work for you as well...
#include <boost/di.hpp>
#include <boost/di/extension/injections/factory.hpp>
namespace di = boost::di;
class App
{
public:
App(const di::extension::ifactory<Interface, int, float>& _user1, const di::extension::ifactory<Interface, int, float>& _user2) :
user1(_user1.create(1, 2.0f)),
user2(_user2.create(2, 3.0f))
{}
std::unique_ptr<Interface, std::default_delete<Interface> > user1;
std::unique_ptr<Interface, std::default_delete<Interface> > user2;
};
int main()
{
const auto inj = [] {
return ::di::make_injector(
di::bind<di::extension::ifactory<Interface, int, float>>().to(di::extension::factory<Impl>{})
);
};
auto app = inj().create<App>();
}
The Interface and Impl classes are the same as above.
Thanks @jferch ! That sounds pretty good actually, I'll give it a try and see how I go.
Expected Behavior
Initialize C as C(A(0.5), B(1U, 1.0), B(2U, 2.0))
Actual Behavior
C is created with default values
Steps to Reproduce the Problem
Specifications