这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 28 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ using IFizzPtr = std::unique_ptr<IFizz>;
```cpp

namespace symbols {
inline extern inversify::Symbol<int> foo {};
inline extern inversify::Symbol<double> bar {};
inline extern inversify::Symbol<IFizzPtr> fizz {};
inline extern inversify::Symbol<std::function<IFizzPtr()>> fizzFactory {};
using foo = inversify::Symbol<int>;
using bar = inversify::Symbol<double>;
using fizz = inversify::Symbol<IFizzPtr>;
using fizzFactory = inversify::Symbol<std::function<IFizzPtr()>>;

inline extern inversify::Symbol<IFizzUniquePtr> autoFizzUnique {};
inline extern inversify::Symbol<IFizzSharedPtr> autoFizzShared {};
using autoFizzUnique = inversify::Symbol<std::function<IFizzUniquePtr>>;
using autoFizzShared = inversify::Symbol<std::function<IFizzSharedPtr>>;
}

```
Expand Down Expand Up @@ -95,10 +95,13 @@ struct Fizz : IFizz {
int counter_ { 0 };
};

inline static auto injectFizz = inversify::Injectable<Fizz>::inject(
symbols::foo,
symbols::bar
);
template <>
struct inversify::Injectable<Fizz> {
using Inject = inversify::Inject<
symbols::foo,
symbols::bar
>;
};

```

Expand All @@ -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<symbols::foo>().toConstantValue(10);
container.bind<symbols::bar>().toConstantValue(1.618);

```

Expand All @@ -131,10 +134,10 @@ Singleton scope dynamic bindings cache the first resolution of the binding.

```cpp

container.bind(symbols::fizz).toDynamicValue(
container.bind<symbols::fizz>().toDynamicValue(
[](const inversify::Context& ctx) {
auto foo = ctx.container.get(symbols::foo);
auto bar = ctx.container.get(symbols::bar);
auto foo = ctx.container.get<symbols::foo>();
auto bar = ctx.container.get<symbols::bar>();

auto fizz = std::make_shared<Fizz>(foo, bar);

Expand All @@ -150,11 +153,11 @@ Dynamic bindings can be used to resolve factory functions.

```cpp

container.bind(symbols::fizzFactory).toDynamicValue(
container.bind<symbols::fizzFactory>().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<symbols::foo>();
auto bar = ctx.container.get<symbols::bar>();

auto fizz = std::make_shared<Fizz>(foo, bar);

Expand All @@ -173,29 +176,29 @@ Automatic bindings can generate instances, unique_ptr's, and shared_ptr's of a c

```cpp

container.bind(symbols::autoFizzUnique).to<Fizz>();
container.bind(symbols::autoFizzShared).to<Fizz>().inSingletonScope();
container.bind<symbols::autoFizzUnique>().to<Fizz>();
container.bind<symbols::autoFizzShared>().to<Fizz>().inSingletonScope();

```

#### Resolving Dependencies

```cpp

auto bar = container.get(symbols::bar);
auto bar = container.get<symbols::bar>();

auto fizz = container.get(symbols::fizz);
auto fizz = container.get<symbols::fizz>();
fizz->buzz();

auto fizzFactory = container.get(symbols::fizzFactory);
auto fizzFactory = container.get<symbols::fizzFactory>();
auto anotherFizz = fizzFactory();
anotherFizz->buzz();


auto autoFizzUnique = container.get(symbols::autoFizzUnique);
auto autoFizzUnique = container.get<symbols::autoFizzUnique>();
autoFizzUnique->buzz();

auto autoFizzShared = container.get(symbols::autoFizzShared);
auto autoFizzShared = container.get<symbols::autoFizzShared>();
autoFizzShared->buzz();

```
Expand Down
1 change: 1 addition & 0 deletions example/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ cc_library(
name = "example_api",
hdrs = glob([
"api/*.hpp",
"src/*.hpp",
]),
includes = [
".",
Expand Down
6 changes: 3 additions & 3 deletions example/api/symbols.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace inversify = mosure::inversify;
namespace symbols {
inline extern inversify::Symbol<ILoggerPtr> logger {};
inline extern inversify::Symbol<IServicePtr> service {};
inline extern inversify::Symbol<ISettings> settings {};
using logger = inversify::Symbol<ILoggerPtr>;
using service = inversify::Symbol<IServicePtr>;
using settings = inversify::Symbol<ISettings>;
}
7 changes: 6 additions & 1 deletion example/src/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ class Logger : public ILogger {
};

namespace inversify = mosure::inversify;
inline static auto injectLogger = inversify::Injectable<Logger>::inject(symbols::settings);
template <>
struct inversify::Injectable<Logger> {
using Inject = inversify::Inject<
symbols::settings
>;
};
8 changes: 4 additions & 4 deletions example/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ namespace inversify = mosure::inversify;
int main() {
inversify::Container container;

container.bind(symbols::logger).to<Logger>().inSingletonScope();
container.bind(symbols::service).to<Service>();
container.bind(symbols::settings).to<Settings>().inSingletonScope();
container.bind<symbols::logger>().to<Logger>().inSingletonScope();
container.bind<symbols::service>().to<Service>();
container.bind<symbols::settings>().to<Settings>().inSingletonScope();

//container.bind<ILoggerPtr>(symbols::logger).to<MockLogger>().inSingletonScope();

container.get(symbols::service)->run();
container.get<symbols::service>()->run();

return 0;
}
3 changes: 0 additions & 3 deletions example/src/mock_logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<MockLogger>::inject();
7 changes: 6 additions & 1 deletion example/src/service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ class Service : public IService {
};

namespace inversify = mosure::inversify;
inline static auto injectService = inversify::Injectable<Service>::inject(symbols::logger);
template <>
struct inversify::Injectable<Service> {
using Inject = inversify::Inject<
symbols::logger
>;
};
3 changes: 0 additions & 3 deletions example/src/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,3 @@ struct Settings : ISettings {
}
}
};

namespace inversify = mosure::inversify;
inline static auto injectSettings = inversify::Injectable<Settings>::inject();
8 changes: 0 additions & 8 deletions include/mosure/binding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,13 @@ namespace mosure::inversify {
template <typename T>
class Binding : public BindingTo<T> {
public:
explicit Binding(const inversify::Symbol<T>& symbol)
:
symbol_(symbol)
{ }

T resolve(const Context& context) const {
if (!this->resolver_) {
throw inversify::exceptions::ResolutionException("inversify::Resolver not found. Malformed binding.");
}

return this->resolver_->resolve(context);
}

private:
const inversify::Symbol<T>& symbol_;
};

}
25 changes: 14 additions & 11 deletions include/mosure/container.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <any>
#include <typeinfo>
#include <unordered_map>
#include <utility>

Expand All @@ -16,36 +17,38 @@ namespace mosure::inversify {
class Container : public inversify::IContainer<Container> {
public:
template <typename T>
inversify::BindingTo<T>& bind(const inversify::Symbol<T>& type) {
static_assert(!std::is_abstract<T>(), "inversify::Container cannot bind/get abstract class value (use a smart pointer instead).");
inversify::BindingTo<typename T::value>& bind() {
auto binding = inversify::Binding<typename T::value>();

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<inversify::Binding<T>&>(bindings_.at(type.id));
return std::any_cast<inversify::Binding<typename T::value>&>(bindings_.at(key));
}

template <typename T>
T get(const inversify::Symbol<T>& 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<inversify::Binding<T>>(symbolBinding->second);
auto binding = std::any_cast<inversify::Binding<typename T::value>>(symbolBinding->second);

return binding.resolve(context_);
}

private:
std::unordered_map<int, std::any> bindings_ { };
std::unordered_map<std::size_t, std::any> bindings_ { };
inversify::Context context_ { *this };
};

Expand Down
69 changes: 10 additions & 59 deletions include/mosure/injectable.hpp
Original file line number Diff line number Diff line change
@@ -1,76 +1,27 @@
#pragma once

#include <memory>
#include <tuple>
#include <type_traits>

#include <mosure/context.hpp>
#include <mosure/factory.hpp>
#include <mosure/meta.hpp>
#include <mosure/symbol.hpp>


namespace mosure::inversify {

template <typename ...Types>
inline constexpr bool valid_inject_types_v = std::conjunction_v<
meta::is_specialization<Types, Symbol>...
>;
template <typename... Dependencies>
struct Inject {
static_assert(meta::valid_inject_types_v<Dependencies...>, "inversify::Injectable dependencies must be of type inversify::Symbol");

template <typename Implementation>
class Injectable {
public:
inline static inversify::Factory<Implementation> factory;
inline static inversify::Factory<std::unique_ptr<Implementation>> factory_unique;
inline static inversify::Factory<std::shared_ptr<Implementation>> factory_shared;

template <typename... Dependencies>
inline static Injectable inject(Dependencies... dependencies) {
static_assert(valid_inject_types_v<Dependencies...>, "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<Implementation>(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<Implementation>(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<Implementation>(resolve_dependency(context, deps)...);
};

return std::apply(expansion, std::move(deps));
};

return Injectable {};
}

private:
template <typename Dependency>
inline static typename Dependency::value resolve_dependency(const inversify::Context& context, Dependency dep) {
using Interface = typename Dependency::value;
auto symbol = static_cast<Symbol<Interface>>(dep);
inline static auto resolve(const inversify::Context& context) {
return std::make_tuple(context.container.get<Dependencies>()...);
}
};

return context.container.get(symbol);
}
template <typename Implementation>
struct Injectable {
using Inject = inversify::Inject<>;
};

}
8 changes: 4 additions & 4 deletions include/mosure/interfaces/icontainer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ namespace mosure::inversify {
class IContainer {
public:
template <typename T>
inversify::BindingTo<T>& bind(const inversify::Symbol<T>& type) {
inversify::BindingTo<typename T::value>& bind() {
auto crtpImplementation = static_cast<Implementation const *>(this);

return crtpImplementation->bind(type);
return crtpImplementation->template bind<T>();
}

template <typename T>
T get(const inversify::Symbol<T>& type) const {
typename T::value get() const {
auto crtpImplementation = static_cast<Implementation const *>(this);

return crtpImplementation->get(type);
return crtpImplementation->template get<T>();
}
};

Expand Down
1 change: 1 addition & 0 deletions include/mosure/inversify.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SOFTWARE.
#include <string> // string
#include <unordered_map> // unordered_map
#include <tuple> // make_from_tuple, tuple
#include <typeinfo> // typeid
#include <type_traits> // apply, conjunction_v, false_type, true_type
#include <utility> // make_pair

Expand Down
8 changes: 8 additions & 0 deletions include/mosure/meta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ namespace mosure::inversify::meta {
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type { };

template <typename ...Types>
inline constexpr bool valid_inject_types_v = std::conjunction_v<
meta::is_specialization<Types, Symbol>...
>;

template <typename T>
using value_t = typename T::value;

}
Loading