这是indexloc提供的服务,不要输入任何密码
Skip to content
Open
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
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ See the [inversify-cpp-visualizer](https://github.com/mosure/inversify-cpp-visua

## Features
* Constant, dynamic, and automatic resolvers
* Singleton, resolution (TODO), and unique scopes
* Singleton, resolution, and unique scopes

## Documentation

Expand Down Expand Up @@ -142,12 +142,25 @@ container.bind<symbols::bar>().toConstantValue(1.618);

Dynamic bindings are resolved when calling `container.get...`.

By default, dynamic bindings have resolution scope (e.g. each call to `container.get...` calls the factory).
By default, dynamic bindings have unique scope (e.g. each call to `container.get...` calls the factory).

Singleton scope dynamic bindings cache the first resolution of the binding.
Resolution scope dynamic bindings cache values during a single resolution graph, ensuring duplicate dependencies resolve to the same value. Use `.inResolutionScope()` to enable this behaviour.

Singleton scope dynamic bindings cache the first resolution of the binding across all calls.

```cpp

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

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

return fizz;
}
).inResolutionScope();

container.bind<symbols::fizz>().toDynamicValue(
[](auto& ctx) {
auto foo = ctx.container.template get<symbols::foo>();
Expand Down
75 changes: 55 additions & 20 deletions example/simple/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
#include <mosure/inversify.hpp>
#include <iostream>
#include <memory>
#include <utility>

#include <mosure/inversify.hpp>

#include <api/symbols.hpp>

Expand All @@ -8,22 +12,53 @@
#include <src/settings.hpp>


namespace inversify = mosure::inversify;

int main() {
inversify::Container<
symbols::logger,
symbols::service,
symbols::settings
> container;

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();

return 0;
}
namespace inversify = mosure::inversify;

struct RequestLog {
RequestLog(ILoggerPtr primary, ILoggerPtr secondary)
: primary_(std::move(primary)), secondary_(std::move(secondary))
{ }

ILoggerPtr primary_;
ILoggerPtr secondary_;
};

using RequestLogPtr = std::shared_ptr<RequestLog>;

namespace request_symbols {
using batchedLog = inversify::Symbol<RequestLogPtr>;
}

template <>
struct inversify::Injectable<RequestLog>
: inversify::Inject<
symbols::logger,
symbols::logger
>
{ };

int main() {
inversify::Container<
symbols::logger,
symbols::service,
symbols::settings,
request_symbols::batchedLog
> container;

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

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

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

auto requestLog = container.get<request_symbols::batchedLog>();
std::cout << std::boolalpha
<< "Resolution scoped logger reused within request: "
<< (requestLog->primary_ == requestLog->secondary_)
<< std::endl;

return 0;
}
4 changes: 4 additions & 0 deletions include/mosure/binding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class BindingScope {
resolver_ = std::make_shared<inversify::CachedResolver<T, SymbolTypes...>>(resolver_);
}

void inResolutionScope() {
resolver_ = std::make_shared<inversify::ResolutionCachedResolver<T, SymbolTypes...>>(resolver_);
}

#ifdef INVERSIFY_BINDING_INSPECTION
auto getResolver() const {
return resolver_;
Expand Down
15 changes: 14 additions & 1 deletion include/mosure/container.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <optional>

Check warning on line 3 in include/mosure/container.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/mosure/container.hpp#L3

Include file: <optional> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <tuple>

#include <mosure/binding.hpp>
Expand Down Expand Up @@ -51,9 +52,21 @@
"inversify::Container symbol not registered"
);

return std::get<
auto* previousScope = context_.resolutionScope;
std::optional<inversify::ResolutionScope> scope;

if (previousScope == nullptr) {
scope.emplace();
context_.resolutionScope = &scope.value();
}

auto result = std::get<
inversify::Binding<T, SymbolTypes...>
>(bindings_).resolve(context_);

context_.resolutionScope = previousScope;

return result;
}

private:
Expand Down
44 changes: 44 additions & 0 deletions include/mosure/context.hpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,60 @@
#pragma once

#include <memory>

Check warning on line 3 in include/mosure/context.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/mosure/context.hpp#L3

Include file: <memory> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <unordered_map>

Check warning on line 4 in include/mosure/context.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/mosure/context.hpp#L4

Include file: <unordered_map> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <utility>

Check warning on line 5 in include/mosure/context.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/mosure/context.hpp#L5

Include file: <utility> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <mosure/interfaces/icontainer.hpp>


namespace mosure::inversify {

class ResolutionScope {
struct CacheEntry {
virtual ~CacheEntry() = default;
};

template <typename T>
struct CacheValue : CacheEntry {
explicit CacheValue(T value)
: value_(std::move(value))
{ }

const T& value() const { return value_; }

private:
T value_;
};

public:
template <typename T>
bool contains(const void* key) const {
return cache_.find(key) != cache_.end();
}

template <typename T>
T get(const void* key) const {
return static_cast<CacheValue<T>*>(cache_.at(key).get())->value();
}

template <typename T>
void set(const void* key, T value) {
cache_[key] = std::make_unique<CacheValue<T>>(std::move(value));
}

void clear() { cache_.clear(); }

private:
std::unordered_map<const void*, std::unique_ptr<CacheEntry>> cache_;
};

template <typename... SymbolTypes>
class Container;

template <typename... SymbolTypes>
struct Context {
inversify::IContainer<Container, SymbolTypes...>& container;
ResolutionScope* resolutionScope { nullptr };

Check warning on line 57 in include/mosure/context.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/mosure/context.hpp#L57

struct member 'Context::resolutionScope' is never used.
};

}
49 changes: 49 additions & 0 deletions include/mosure/resolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>

Check warning on line 7 in include/mosure/resolver.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

include/mosure/resolver.hpp#L7

Include file: <utility> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#ifdef INVERSIFY_BINDING_INSPECTION
#include <string>
Expand Down Expand Up @@ -268,4 +269,52 @@
ResolverPtr<T, SymbolTypes...> parent_;
};

template <
typename T,
typename... SymbolTypes
>
class ResolutionCachedResolver
: public Resolver<T, SymbolTypes...> {
static_assert(
std::is_copy_constructible_v<T>,
"inversify::ResolutionCachedResolver requires a copy constructor. Are you caching a unique_ptr?"
);

public:
explicit ResolutionCachedResolver(ResolverPtr<T, SymbolTypes...> parent)
: parent_(std::move(parent))
{ }

inline T resolve(const inversify::Context<SymbolTypes...>& context) override {
if (!context.resolutionScope) {
return parent_->resolve(context);
}

auto key = static_cast<const void*>(this);
auto& scope = *context.resolutionScope;

if (scope.template contains<T>(key)) {
return scope.template get<T>(key);
}

auto value = parent_->resolve(context);
scope.template set<T>(key, value);

return value;
}

#ifdef INVERSIFY_BINDING_INSPECTION
inline virtual std::string getResolverLabel() const override {
return std::string("resolution - ") + parent_->getResolverLabel();
}

inline virtual std::string getImplementationLabel() const override {
return parent_->getImplementationLabel();
}
#endif

private:
ResolverPtr<T, SymbolTypes...> parent_;
};

}
Loading
Loading