#ifndef MEMGRAPH_UTILS_IOC_CONTAINER_HPP #define MEMGRAPH_UTILS_IOC_CONTAINER_HPP #include #include #include #include namespace ioc { class Container { struct Holdable { using uptr = std::unique_ptr; Holdable() = default; virtual ~Holdable() = default; }; template struct Item : public Holdable { virtual std::shared_ptr get() = 0; }; template struct Instance : public Item { Instance(std::shared_ptr item) : item(std::move(item)) {} Instance(std::shared_ptr&& item) : item(item) {} std::shared_ptr get() override { assert(item != nullptr); return item; } std::shared_ptr item; }; template struct Creator : public Item { using func = std::function()>; Creator(func&& f) : f(f) {} std::shared_ptr get() override { return f(); } func f; }; public: template std::shared_ptr resolve() { auto it = items.find(key()); assert(it != items.end()); // try to cast Holdable* to Item* auto item = dynamic_cast*>(it->second.get()); assert(item != nullptr); return item->get(); } template std::shared_ptr singleton() { auto item = std::make_shared(resolve()...); items.emplace(key(), Holdable::uptr(new Instance(item))); return item; } template void singleton(std::shared_ptr&& item) { items.emplace(key(), Holdable::uptr(new Instance(item))); } template void factory(typename Creator::func&& f) { items[key()] = std::move(Holdable::uptr( new Creator(std::forward::func>(f)) )); } private: std::map items; template std::string key() { return typeid(T).name(); } }; } #endif