-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Service map autowire with polymorphic services #111
Comments
Another nice option might be too let users pass a list of types as variadic template parameters to the new alias. This would allow you to not have as many aliases while also allowing for autowiring of supplied services and similar functionality that is just implemented as simple tags. |
So I took a closer look at this. The latter idea is somewhat hard to implement due to it requiring that information to be passed pretty much through the whole autowire stack. Creating the corresponding |
Hi! Yeah, polymorphic services has not been added to the default autowire mapper. Probably an oversight on my part since I'm not using them much. An autowire mapper that supports it might be implemented like so: template<typename... Overrides>
struct autowire_polymorphic {
template<typename T>
struct Service : kgr::single_service<T, kgr::autowire>, kgr::overrides<kgr::mapped_service_t<Overrides>> {};
template<typename T>
using mapped_service = Service<std::decay_t<T>, kgr::autowire>;
};
struct autowire_abstract {
template<typename T>
struct Service : kgr::abstract_service<T> {};
template<typename T>
using mapped_service = Service<std::decay_t<T>>;
}; I haven't tried since I'm on mobile, but you should be able to use is like this: struct my_type_abstract {
virtual ~my_type_abstract() = default;
virtual void foo() = 0;
friend auto service_map(my_type_abstract const&) -> autowire_abstract;
};
struct my_type_override : my_type_abstract {
void foo() override {}
friend auto service_map(my_type_override const&) -> autowire_polymorphic<my_type_abstract>;
}; It works because the Let me know if it helps! |
Doesn't quite seem to work. Fixing some minor details I ended up with template<typename... Overrides>
struct autowire_polymorphic {
template<typename T>
struct Service : kgr::single_service<T, kgr::autowire>, kgr::overrides<kgr::mapped_service_t<Overrides>...> {};
template<typename T>
using mapped_service = Service<std::decay_t<T>>;
}; However this complains
and frankly I don't know enough about the internals of kangaru to diagnose this. With abstract I get bigger problems yet, as it does not seem to be registering properly inside the autowiring and isn't even found by |
Update: After a bit of thinking about this for myself, I tried it with actually having two separate indirect maps for the polymorphic and override classes. That worked: template<typename... Overrides>
struct autowire_override {
template<typename T>
struct Service : kgr::single_service<T, kgr::autowire>, kgr::overrides<kgr::mapped_service_t<Overrides>...> {};
template<typename T>
using mapped_service = Service<std::decay_t<T>>;
};
struct autowire_polymorphic {
template<typename T>
struct Service : kgr::single_service<T, kgr::autowire>, kgr::polymorphic {};
template<typename T>
using mapped_service = Service<std::decay_t<T>>;
}; (The docs of this project are honestly excellent-despite the complexity of the template hell that it is) Still I don't know how to make abstract work-but I don't need that anyway for my case. I'll leave this open though as it seems you agree this should be a standard component. |
Hey! Sorry for the delay. I modified example 3 to work with autowire. Here's the full example, with abstract services working.
Thank you! I'm trying my best, both to make the doc better and to make it less of a template hell. Feedback like yours is really helpful getting the small details. To make abstract service working, you still need to define at runtime which service the container will be using. This is done through overrides. Anyway, here's the code. Let me know if it works for you! I'm looking forward making this a builtin feature. #include <kangaru/kangaru.hpp>
#include <iostream>
struct autowire_abstract {
template<typename T>
struct Service : kgr::abstract_service<T> {};
template<typename T>
using mapped_service = Service<std::decay_t<T>>;
};
template<typename... Overrides>
struct autowire_override {
template<typename T>
struct Service : kgr::single_service<T, kgr::autowire>, kgr::overrides<kgr::mapped_service_t<Overrides>...> {};
template<typename T>
using mapped_service = Service<std::decay_t<T>>;
};
struct autowire_polymorphic {
template<typename T>
struct Service : kgr::single_service<T, kgr::autowire>, kgr::polymorphic {};
template<typename T>
using mapped_service = Service<std::decay_t<T>>;
};
struct AbstractCamera {
virtual void projection() = 0;
friend auto service_map(AbstractCamera const&) -> autowire_abstract;
};
struct Camera : AbstractCamera {
void projection() override {
std::cout << "default projection" << std::endl;
}
friend auto service_map(Camera const&) -> autowire_override<AbstractCamera>;
};
struct PerspectiveCamera : Camera {
void projection() override {
std::cout << "perspective projection" << std::endl;
}
friend auto service_map(PerspectiveCamera const&) -> autowire_override<Camera, AbstractCamera>;
};
struct OrthogonalCamera : Camera {
void projection() override {
std::cout << "orthogonal projection" << std::endl;
}
friend auto service_map(OrthogonalCamera const&) -> autowire_override<Camera, AbstractCamera>;
};
int main()
{
auto c = kgr::container{};
c.emplace<kgr::mapped_service_t<Camera>>();
c.invoke([](AbstractCamera& c) {
c.projection();
});
c.emplace<kgr::mapped_service_t<OrthogonalCamera>>();
c.invoke([](Camera& c) {
c.projection();
});
} Output:
|
@gracicot any news on this? It would be really nice to have this in. |
@wopss I will release v4.4.0 for this, it's quite easy to add. PR appreciated, but I'll probably find some time in the coming months |
Is your feature request related to a problem? Please describe.
I'm trying to auto wire polymorphic services in the simplest way possible.
Describe the solution you'd like
I'd like to be able to do this through the service map.
Describe alternatives you've considered
So far this can only be done with services that you define yourself and then use autowire to detect the dependencies.
Additional context
This should by all accounts be as simple as just adding a few more definitions and aliases, inheriting from both the four existing services and
kgr::polymorphic
inautowire.hpp
. Might give this a shot myself in a PR. Given that I don't have an overview of this I can't say if I may be missing something though.The text was updated successfully, but these errors were encountered: