| /* |
| * Copyright 2014 Google Inc. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef FRUIT_INJECTOR_H |
| #define FRUIT_INJECTOR_H |
| |
| // This include is not required here, but having it here shortens the include trace in error messages. |
| #include <fruit/impl/injection_errors.h> |
| |
| #include <fruit/component.h> |
| #include <fruit/normalized_component.h> |
| #include <fruit/provider.h> |
| #include <fruit/impl/meta_operation_wrappers.h> |
| |
| namespace fruit { |
| |
| /** |
| * An injector is a class constructed from a component that performs the needed injections and manages the lifetime of |
| * the created objects. |
| * An injector does *not* need to specify all types bound in the component; you can only specify the "root" type(s) and |
| * the injector will also create and store the instances of classes that are needed (directly or indirectly) to inject |
| * the root types. |
| * |
| * Example usage: |
| * |
| * Component<Foo, Bar> getFooBarComponent() { |
| * ... |
| * } |
| * |
| * Injector<Foo, Bar> injector(getFooBarComponent); |
| * Foo* foo = injector.get<Foo*>(); |
| * Bar* bar(injector); // Equivalent to: Bar* bar = injector.get<Bar*>(); |
| */ |
| template <typename... P> |
| class Injector { |
| public: |
| // Moving injectors is allowed. |
| Injector(Injector&&) noexcept = default; |
| |
| // Copying injectors is forbidden. |
| Injector(const Injector&) = delete; |
| |
| /** |
| * This creates an injector from a component function (that can optionally have parameters). |
| * |
| * Args and FormalArgs (if any) must be the same types; or to be precise, each type in Args must be convertible into |
| * the corresponding type in FormalArgs. |
| * |
| * Example usage: |
| * |
| * Component<Foo, Bar> getFooBarComponent() { |
| * ... |
| * } |
| * |
| * Injector<Foo, Bar> injector(getFooBarComponent); |
| * Foo* foo = injector.get<Foo*>(); |
| * Bar* bar(injector); // Equivalent to: Bar* bar = injector.get<Bar*>(); |
| * |
| * Example usage with arguments: |
| * |
| * Component<Foo, Bar> getFooBarComponent(int n, double d) { |
| * ... |
| * } |
| * |
| * Injector<Foo, Bar> injector(getFooBarComponent, 10, 3.14); |
| * Foo* foo = injector.get<Foo*>(); |
| */ |
| template <typename... FormalArgs, typename... Args> |
| explicit Injector(Component<P...> (*)(FormalArgs...), Args&&... args); |
| |
| /** |
| * This creates an injector from a normalized component and a component function. |
| * See the documentation of NormalizedComponent for more details. |
| * |
| * Args and FormalArgs (if any) must be the same types; or to be precise, each type in Args must be convertible into |
| * the corresponding type in FormalArgs. |
| * |
| * The NormalizedComponent can have requirements, but the Component can't. |
| * The NormalizedComponent must remain valid during the lifetime of any Injector object constructed with it. |
| * |
| * Example usage: |
| * |
| * // In the global scope. |
| * Component<Request> getRequestComponent(Request* request) { |
| * return fruit::createComponent() |
| * .bindInstance(*request); |
| * } |
| * |
| * // At startup (e.g. inside main()). |
| * NormalizedComponent<Required<Request>, Bar, Bar2> normalizedComponent = ...; |
| * |
| * ... |
| * for (...) { |
| * // For each request. |
| * Request request = ...; |
| * |
| * Injector<Foo, Bar> injector(normalizedComponent, getRequestComponent, &request); |
| * Foo* foo = injector.get<Foo*>(); |
| * ... |
| * } |
| */ |
| template <typename... NormalizedComponentParams, typename... ComponentParams, typename... FormalArgs, |
| typename... Args> |
| Injector(const NormalizedComponent<NormalizedComponentParams...>& normalized_component, |
| Component<ComponentParams...> (*)(FormalArgs...), Args&&... args); |
| |
| /** |
| * Deleted constructor, to ensure that constructing an Injector from a temporary NormalizedComponent doesn't compile. |
| */ |
| template <typename... NormalizedComponentParams, typename... ComponentParams, typename... FormalArgs, |
| typename... Args> |
| Injector(NormalizedComponent<NormalizedComponentParams...>&& normalized_component, |
| Component<ComponentParams...> (*)(FormalArgs...), Args&&... args) = delete; |
| |
| /** |
| * Returns an instance of the specified type. For any class C in the Injector's template parameters, the following |
| * variations are allowed: |
| * |
| * get<C>() |
| * get<C*>() |
| * get<C&>() |
| * get<const C*>() |
| * get<const C&>() |
| * get<shared_ptr<C>>() |
| * get<Provider<C>>() |
| * get<Provider<const C>>() |
| * get<Annotated<Annotation, C>>() (for any type `Annotation') |
| * get<Annotated<Annotation, C*>>() (for any type `Annotation') |
| * get<Annotated<Annotation, C&>>() (for any type `Annotation') |
| * get<Annotated<Annotation, const C*>>() (for any type `Annotation') |
| * get<Annotated<Annotation, const C&>>() (for any type `Annotation') |
| * get<Annotated<Annotation, shared_ptr<C>>>() (for any type `Annotation') |
| * get<Annotated<Annotation, Provider<C>>>() (for any type `Annotation') |
| * get<Annotated<Annotation, Provider<const C>>>() (for any type `Annotation') |
| * |
| * For any "const C" in the Injector's template parameters, only a subset of those are allowed, specifically: |
| * |
| * get<C>() |
| * get<const C*>() |
| * get<const C&>() |
| * get<Provider<const C>>() |
| * get<Annotated<Annotation, C>>() (for any type `Annotation') |
| * get<Annotated<Annotation, const C*>>() (for any type `Annotation') |
| * get<Annotated<Annotation, const C&>>() (for any type `Annotation') |
| * get<Annotated<Annotation, Provider<const C>>>() (for any type `Annotation') |
| * |
| * With a non-annotated parameter T, this returns a T. |
| * With an annotated parameter AnnotatedT=Annotated<Annotation, T>, this returns a T. |
| * E.g. if you want to inject a pointer for an annotated type, you can use this as follows: |
| * |
| * T* instance = injector.get<Annotated<Annotation, T*>>(); |
| * |
| * The shared_ptr versions come with a slight performance hit, prefer injecting pointers or references if possible. |
| * Calling get<> repeatedly for the same class with the same injector will return the same instance. |
| */ |
| template <typename T> |
| fruit::impl::RemoveAnnotations<T> get(); |
| |
| /** |
| * This is a convenient way to call get(). E.g.: |
| * |
| * MyInterface* x(injector); |
| * |
| * is equivalent to: |
| * |
| * MyInterface* x = injector.get<MyInterface*>(); |
| * |
| * Note that this can't be used to inject an annotated type, i.e. this does NOT work: |
| * |
| * fruit::Annotated<SomeAnnotation, SomeClass> foo(injector); |
| * |
| * Because foo would be of type fruit::Annotated, not of type SomeClass. In that case you must use get() instead, |
| * e.g.: |
| * |
| * SomeClass* foo = injector.get<fruit::Annotated<SomeAnnotation, SomeClass*>>();; |
| */ |
| template <typename T> |
| explicit operator T(); |
| |
| /** |
| * Gets all multibindings for a type T. |
| * |
| * Multibindings are independent from bindings; so if there is a (normal) binding for T, that is not returned. |
| * This returns an empty vector if there are no multibindings. |
| * |
| * With a non-annotated parameter T, this returns a const std::vector<T*>&. |
| * With an annotated parameter AnnotatedT=Annotated<Annotation, T>, this returns a const std::vector<T*>&. |
| */ |
| template <typename T> |
| const std::vector<fruit::impl::RemoveAnnotations<T>*>& getMultibindings(); |
| |
| /** |
| * This method is deprecated since Fruit injectors can now be accessed concurrently by multiple threads. This will be |
| * removed in a future Fruit release. |
| * |
| * Eagerly injects all reachable bindings and multibindings of this injector. |
| * This only creates instances of the types that are either: |
| * - exposed by this Injector (i.e. in the Injector's type parameters) |
| * - bound by a multibinding |
| * - needed to inject one of the above (directly or indirectly) |
| * |
| * Unreachable bindings (i.e. bindings that are not exposed by this Injector, and that are not used by any reachable |
| * binding) are not processed. Bindings that are only used lazily, using a Provider, are NOT eagerly injected. |
| * |
| * Also note that this guarantee doesn't apply to Providers. |
| */ |
| FRUIT_DEPRECATED_DECLARATION(void eagerlyInjectAll()); |
| |
| private: |
| using Check1 = typename fruit::impl::meta::CheckIfError<fruit::impl::meta::Eval< |
| fruit::impl::meta::CheckNoRequiredTypesInInjectorArguments(fruit::impl::meta::Type<P>...)>>::type; |
| // Force instantiation of Check1. |
| static_assert(true || sizeof(Check1), ""); |
| |
| using Comp = fruit::impl::meta::Eval<fruit::impl::meta::ConstructComponentImpl(fruit::impl::meta::Type<P>...)>; |
| |
| using Check2 = typename fruit::impl::meta::CheckIfError<Comp>::type; |
| using VoidType = fruit::impl::meta::Type<void>; |
| // Force instantiation of Check2. |
| static_assert(true || sizeof(Check2), ""); |
| using Check3 = typename fruit::impl::meta::CheckIfError<fruit::impl::meta::Eval<fruit::impl::meta::If( |
| fruit::impl::meta::Not(fruit::impl::meta::IsEmptySet(typename Comp::RsSuperset)), |
| fruit::impl::meta::ConstructErrorWithArgVector(fruit::impl::InjectorWithRequirementsErrorTag, |
| fruit::impl::meta::SetToVector(typename Comp::RsSuperset)), |
| VoidType)>>::type; |
| // Force instantiation of Check3. |
| static_assert(true || sizeof(Check3), ""); |
| |
| friend struct fruit::impl::InjectorAccessorForTests; |
| |
| std::unique_ptr<fruit::impl::InjectorStorage> storage; |
| }; |
| |
| } // namespace fruit |
| |
| #include <fruit/impl/injector.defn.h> |
| |
| #endif // FRUIT_INJECTOR_H |