diff --git a/README.md b/README.md index b1db58d..19c2469 100644 --- a/README.md +++ b/README.md @@ -60,13 +60,13 @@ using IFizzPtr = std::unique_ptr; ```cpp namespace symbols { - inline extern inversify::Symbol foo {}; - inline extern inversify::Symbol bar {}; - inline extern inversify::Symbol fizz {}; - inline extern inversify::Symbol> fizzFactory {}; + using foo = inversify::Symbol; + using bar = inversify::Symbol; + using fizz = inversify::Symbol; + using fizzFactory = inversify::Symbol>; - inline extern inversify::Symbol autoFizzUnique {}; - inline extern inversify::Symbol autoFizzShared {}; + using autoFizzUnique = inversify::Symbol>; + using autoFizzShared = inversify::Symbol>; } ``` @@ -95,10 +95,13 @@ struct Fizz : IFizz { int counter_ { 0 }; }; -inline static auto injectFizz = inversify::Injectable::inject( - symbols::foo, - symbols::bar -); +template <> +struct inversify::Injectable { + using Inject = inversify::Inject< + symbols::foo, + symbols::bar + >; +}; ``` @@ -116,8 +119,8 @@ Constant bindings are always singletons. ```cpp -container.bind(symbols::foo).toConstantValue(10); -container.bind(symbols::bar).toConstantValue(1.618); +container.bind().toConstantValue(10); +container.bind().toConstantValue(1.618); ``` @@ -131,10 +134,10 @@ Singleton scope dynamic bindings cache the first resolution of the binding. ```cpp -container.bind(symbols::fizz).toDynamicValue( +container.bind().toDynamicValue( [](const inversify::Context& ctx) { - auto foo = ctx.container.get(symbols::foo); - auto bar = ctx.container.get(symbols::bar); + auto foo = ctx.container.get(); + auto bar = ctx.container.get(); auto fizz = std::make_shared(foo, bar); @@ -150,11 +153,11 @@ Dynamic bindings can be used to resolve factory functions. ```cpp -container.bind(symbols::fizzFactory).toDynamicValue( +container.bind().toDynamicValue( [](const inversify::Context& ctx) { return [&]() { - auto foo = ctx.container.get(symbols::foo); - auto bar = ctx.container.get(symbols::bar); + auto foo = ctx.container.get(); + auto bar = ctx.container.get(); auto fizz = std::make_shared(foo, bar); @@ -173,8 +176,8 @@ Automatic bindings can generate instances, unique_ptr's, and shared_ptr's of a c ```cpp -container.bind(symbols::autoFizzUnique).to(); -container.bind(symbols::autoFizzShared).to().inSingletonScope(); +container.bind().to(); +container.bind().to().inSingletonScope(); ``` @@ -182,20 +185,20 @@ container.bind(symbols::autoFizzShared).to().inSingletonScope(); ```cpp -auto bar = container.get(symbols::bar); +auto bar = container.get(); -auto fizz = container.get(symbols::fizz); +auto fizz = container.get(); fizz->buzz(); -auto fizzFactory = container.get(symbols::fizzFactory); +auto fizzFactory = container.get(); auto anotherFizz = fizzFactory(); anotherFizz->buzz(); -auto autoFizzUnique = container.get(symbols::autoFizzUnique); +auto autoFizzUnique = container.get(); autoFizzUnique->buzz(); -auto autoFizzShared = container.get(symbols::autoFizzShared); +auto autoFizzShared = container.get(); autoFizzShared->buzz(); ``` diff --git a/example/BUILD b/example/BUILD index 64f107d..2e4692a 100644 --- a/example/BUILD +++ b/example/BUILD @@ -5,6 +5,7 @@ cc_library( name = "example_api", hdrs = glob([ "api/*.hpp", + "src/*.hpp", ]), includes = [ ".", diff --git a/example/api/symbols.hpp b/example/api/symbols.hpp index d6af5f1..879ef2a 100644 --- a/example/api/symbols.hpp +++ b/example/api/symbols.hpp @@ -9,7 +9,7 @@ namespace inversify = mosure::inversify; namespace symbols { - inline extern inversify::Symbol logger {}; - inline extern inversify::Symbol service {}; - inline extern inversify::Symbol settings {}; + using logger = inversify::Symbol; + using service = inversify::Symbol; + using settings = inversify::Symbol; } diff --git a/example/src/logger.hpp b/example/src/logger.hpp index 812d40e..1030089 100644 --- a/example/src/logger.hpp +++ b/example/src/logger.hpp @@ -54,4 +54,9 @@ class Logger : public ILogger { }; namespace inversify = mosure::inversify; -inline static auto injectLogger = inversify::Injectable::inject(symbols::settings); +template <> +struct inversify::Injectable { + using Inject = inversify::Inject< + symbols::settings + >; +}; diff --git a/example/src/main.cpp b/example/src/main.cpp index 2ca9f27..19034f5 100644 --- a/example/src/main.cpp +++ b/example/src/main.cpp @@ -13,13 +13,13 @@ namespace inversify = mosure::inversify; int main() { inversify::Container container; - container.bind(symbols::logger).to().inSingletonScope(); - container.bind(symbols::service).to(); - container.bind(symbols::settings).to().inSingletonScope(); + container.bind().to().inSingletonScope(); + container.bind().to(); + container.bind().to().inSingletonScope(); //container.bind(symbols::logger).to().inSingletonScope(); - container.get(symbols::service)->run(); + container.get()->run(); return 0; } diff --git a/example/src/mock_logger.hpp b/example/src/mock_logger.hpp index a0e5cf3..2e21b77 100644 --- a/example/src/mock_logger.hpp +++ b/example/src/mock_logger.hpp @@ -13,6 +13,3 @@ class MockLogger : public ILogger { void error(const std::string&) const override { }; void log(LogLevel, const std::string&) const override { }; }; - -namespace inversify = mosure::inversify; -inline static auto injectMockLogger = inversify::Injectable::inject(); diff --git a/example/src/service.hpp b/example/src/service.hpp index eb04be1..dcb489e 100644 --- a/example/src/service.hpp +++ b/example/src/service.hpp @@ -25,4 +25,9 @@ class Service : public IService { }; namespace inversify = mosure::inversify; -inline static auto injectService = inversify::Injectable::inject(symbols::logger); +template <> +struct inversify::Injectable { + using Inject = inversify::Inject< + symbols::logger + >; +}; diff --git a/example/src/settings.hpp b/example/src/settings.hpp index 3d1a779..58c41df 100644 --- a/example/src/settings.hpp +++ b/example/src/settings.hpp @@ -22,6 +22,3 @@ struct Settings : ISettings { } } }; - -namespace inversify = mosure::inversify; -inline static auto injectSettings = inversify::Injectable::inject(); diff --git a/include/mosure/binding.hpp b/include/mosure/binding.hpp index 5a853b8..cafa34b 100644 --- a/include/mosure/binding.hpp +++ b/include/mosure/binding.hpp @@ -46,11 +46,6 @@ namespace mosure::inversify { template class Binding : public BindingTo { public: - explicit Binding(const inversify::Symbol& symbol) - : - symbol_(symbol) - { } - T resolve(const Context& context) const { if (!this->resolver_) { throw inversify::exceptions::ResolutionException("inversify::Resolver not found. Malformed binding."); @@ -58,9 +53,6 @@ namespace mosure::inversify { return this->resolver_->resolve(context); } - - private: - const inversify::Symbol& symbol_; }; } diff --git a/include/mosure/container.hpp b/include/mosure/container.hpp index e4a1015..794ebc0 100644 --- a/include/mosure/container.hpp +++ b/include/mosure/container.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -16,36 +17,38 @@ namespace mosure::inversify { class Container : public inversify::IContainer { public: template - inversify::BindingTo& bind(const inversify::Symbol& type) { - static_assert(!std::is_abstract(), "inversify::Container cannot bind/get abstract class value (use a smart pointer instead)."); + inversify::BindingTo& bind() { + auto binding = inversify::Binding(); - auto binding = inversify::Binding(type); + auto key = typeid(T).hash_code(); - auto lookup = bindings_.find(type.id); + auto lookup = bindings_.find(key); if (lookup != bindings_.end()) { - bindings_.erase(type.id); + bindings_.erase(key); } - auto pair = std::make_pair(type.id, std::any(binding)); + auto pair = std::make_pair(key, std::any(binding)); bindings_.insert(pair); - return std::any_cast&>(bindings_.at(type.id)); + return std::any_cast&>(bindings_.at(key)); } template - T get(const inversify::Symbol& type) const { - auto symbolBinding = bindings_.find(type.id); + typename T::value get() const { + auto key = typeid(T).hash_code(); + + auto symbolBinding = bindings_.find(key); if (symbolBinding == bindings_.end()) { throw inversify::exceptions::SymbolException(); } - auto binding = std::any_cast>(symbolBinding->second); + auto binding = std::any_cast>(symbolBinding->second); return binding.resolve(context_); } private: - std::unordered_map bindings_ { }; + std::unordered_map bindings_ { }; inversify::Context context_ { *this }; }; diff --git a/include/mosure/injectable.hpp b/include/mosure/injectable.hpp index 6e30d01..fe90838 100644 --- a/include/mosure/injectable.hpp +++ b/include/mosure/injectable.hpp @@ -1,76 +1,27 @@ #pragma once -#include #include #include #include -#include #include #include namespace mosure::inversify { - template - inline constexpr bool valid_inject_types_v = std::conjunction_v< - meta::is_specialization... - >; + template + struct Inject { + static_assert(meta::valid_inject_types_v, "inversify::Injectable dependencies must be of type inversify::Symbol"); - template - class Injectable { - public: - inline static inversify::Factory factory; - inline static inversify::Factory> factory_unique; - inline static inversify::Factory> factory_shared; - - template - inline static Injectable inject(Dependencies... dependencies) { - static_assert(valid_inject_types_v, "inversify::Injectable dependencies must be of type inversify::Symbol"); - - factory = [ - deps = std::make_tuple(dependencies...) - ](const inversify::Context& context) mutable { - auto expansion = [&context](auto&& ... deps){ - auto args = std::make_tuple(resolve_dependency(context, deps)...); - - return std::make_from_tuple(args); - }; - - return std::apply(expansion, std::move(deps)); - }; - - factory_unique = [ - deps = std::make_tuple(dependencies...) - ](const inversify::Context& context) mutable { - auto expansion = [&context](auto&& ... deps){ - return std::make_unique(resolve_dependency(context, deps)...); - }; - - return std::apply(expansion, std::move(deps)); - }; - - factory_shared = [ - deps = std::make_tuple(dependencies...) - ](const inversify::Context& context) mutable { - auto expansion = [&context](auto&& ... deps){ - return std::make_shared(resolve_dependency(context, deps)...); - }; - - return std::apply(expansion, std::move(deps)); - }; - - return Injectable {}; - } - - private: - template - inline static typename Dependency::value resolve_dependency(const inversify::Context& context, Dependency dep) { - using Interface = typename Dependency::value; - auto symbol = static_cast>(dep); + inline static auto resolve(const inversify::Context& context) { + return std::make_tuple(context.container.get()...); + } + }; - return context.container.get(symbol); - } + template + struct Injectable { + using Inject = inversify::Inject<>; }; } diff --git a/include/mosure/interfaces/icontainer.hpp b/include/mosure/interfaces/icontainer.hpp index b580305..10bdb3c 100644 --- a/include/mosure/interfaces/icontainer.hpp +++ b/include/mosure/interfaces/icontainer.hpp @@ -14,17 +14,17 @@ namespace mosure::inversify { class IContainer { public: template - inversify::BindingTo& bind(const inversify::Symbol& type) { + inversify::BindingTo& bind() { auto crtpImplementation = static_cast(this); - return crtpImplementation->bind(type); + return crtpImplementation->template bind(); } template - T get(const inversify::Symbol& type) const { + typename T::value get() const { auto crtpImplementation = static_cast(this); - return crtpImplementation->get(type); + return crtpImplementation->template get(); } }; diff --git a/include/mosure/inversify.hpp b/include/mosure/inversify.hpp index e51bf60..beb33fd 100644 --- a/include/mosure/inversify.hpp +++ b/include/mosure/inversify.hpp @@ -35,6 +35,7 @@ SOFTWARE. #include // string #include // unordered_map #include // make_from_tuple, tuple +#include // typeid #include // apply, conjunction_v, false_type, true_type #include // make_pair diff --git a/include/mosure/meta.hpp b/include/mosure/meta.hpp index a14b925..a6b9801 100644 --- a/include/mosure/meta.hpp +++ b/include/mosure/meta.hpp @@ -12,4 +12,12 @@ namespace mosure::inversify::meta { template