| /* |
| * 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_COMPONENT_H |
| #define FRUIT_COMPONENT_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/fruit_forward_decls.h> |
| #include <fruit/impl/bindings.h> |
| #include <fruit/impl/component_functors.defn.h> |
| #include <fruit/impl/component_storage/component_storage.h> |
| #include <fruit/impl/component_storage/partial_component_storage.h> |
| #include <fruit/impl/meta/component.h> |
| |
| namespace fruit { |
| |
| /** |
| * A component (aka module) represents a collection of bindings. |
| * You can think of a Component object as a UML component. |
| * |
| * The parameters can be of the form <P...> or <Required<R...>, P...> where: |
| * * R... are the required types (types required to inject some types in P... but that are not provided by this |
| * Component), if any |
| * * P... are the types provided by this Component. |
| * No type can appear twice, not even once in R and once in P. |
| * |
| * See PartialComponent below for how to construct a Component. |
| */ |
| template <typename... Params> |
| class Component { |
| public: |
| Component(Component&&) noexcept = default; |
| |
| Component& operator=(Component&&) = delete; |
| Component& operator=(const Component&) = delete; |
| |
| /** |
| * Converts a PartialComponent to an arbitrary Component, auto-injecting the missing types (if |
| * any). |
| * This is usually called implicitly when returning a component from a function. See PartialComponent for an example. |
| */ |
| template <typename... Bindings> |
| Component(PartialComponent<Bindings...>&& component) noexcept; // NOLINT(google-explicit-constructor) |
| |
| private: |
| // Do not use. Use fruit::createComponent() instead. |
| Component() = default; |
| |
| template <typename... Types> |
| friend class Component; |
| |
| template <typename... Bindings> |
| friend class PartialComponent; |
| |
| template <typename... OtherParams> |
| friend class NormalizedComponent; |
| |
| template <typename... OtherParams> |
| friend class Injector; |
| |
| template <typename... Bindings> |
| friend class fruit::impl::PartialComponentStorage; |
| |
| template <typename Component, typename... Args> |
| friend class fruit::impl::LazyComponentImpl; |
| |
| friend struct fruit::impl::ComponentStorageEntry::LazyComponentWithNoArgs; |
| |
| template <typename Component, typename... Args> |
| friend class fruit::impl::ComponentInterfaceImpl; |
| |
| fruit::impl::ComponentStorage storage; |
| |
| using Comp = fruit::impl::meta::Eval<fruit::impl::meta::ConstructComponentImpl(fruit::impl::meta::Type<Params>...)>; |
| |
| using Check1 = typename fruit::impl::meta::CheckIfError<Comp>::type; |
| // Force instantiation of Check1. |
| static_assert(true || sizeof(Check1), ""); |
| }; |
| |
| /** |
| * Constructs an empty component. |
| * |
| * Example usage: |
| * |
| * fruit::Component<Foo> getFooComponent() { |
| * return fruit::createComponent() |
| * .install(getComponent1) |
| * .install(getComponent2) |
| * .bind<Foo, FooImpl>(); |
| * } |
| * |
| * Since types are auto-injected when needed, just converting this to the desired component can suffice in some cases, |
| * e.g.: |
| * |
| * fruit::Component<Foo> getFooComponent() { |
| * return fruit::createComponent(); |
| * } |
| * |
| * That works if Foo has an Inject typedef or a constructor wrapped in INJECT. |
| */ |
| PartialComponent<> createComponent(); |
| |
| /** |
| * A partially constructed component. |
| * |
| * Client code should never write `PartialComponent'; always start the construction of a component with |
| * fruit::createComponent(), and end it by casting the PartialComponent to the desired Component (often done implicitly |
| * by returning a PartialComponent from a function that has Component<...> as the return type). |
| * |
| * The template parameter is used to propagate information about bound types, it is purely an implementation detail; |
| * users of the Fruit library can pretend that this class is not templated, in no case a specific template parameter is |
| * required. All methods of this class return a PartialComponent, which allows to chain method invocations without |
| * declaring a variable of type PartialComponent. |
| * |
| * Example usage: |
| * |
| * fruit::Component<Foo> getFooComponent() { |
| * return fruit::createComponent() |
| * .install(getComponent1) |
| * .install(getComponent2) |
| * .bind<Foo, FooImpl>(); |
| * } |
| * |
| * Note that no variable of type PartialComponent has been declared; this class should only be used for temporary |
| * values. |
| */ |
| template <typename... Bindings> |
| class PartialComponent { |
| public: |
| PartialComponent& operator=(PartialComponent&&) = delete; |
| PartialComponent& operator=(const PartialComponent&) = delete; |
| |
| /** |
| * This tells Fruit that "the implementation of I is C". |
| * I must be a base class of C, and it's typically (but not necessarily) an abstract class. |
| * C is typically a concrete class, but it doesn't have to be: for example, if A inherits from B and B inherits from C |
| * you can specify bind<C, B>() and bind<B, A>(). |
| * |
| * The most common use of this is to bind the type I to the type C, for example: |
| * |
| * class MyInterface { |
| * public: |
| * virtual void foo() = 0; |
| * }; |
| * |
| * class MyImplementation { |
| * public: |
| * INJECT(MyImplementation()) {} |
| * |
| * void foo() { |
| * ... |
| * } |
| * }; |
| * |
| * fruit::Component<MyInterface> getMyInterfaceComponent() { |
| * return fruit::createComponent() |
| * .bind<MyInterface, MyImplementation>(); |
| * } |
| * |
| * The implementation class can be bound in any way, it doesn't need to be bound using constructor injection as above |
| * (although that's a very common use case). |
| * |
| * You can bind an interface to a type bound using a constant binding (see the bindInstance method that takes a const& |
| * for more details), however the interface will then also be considered bound with a constant binding, and you must |
| * declare that in the returned Component's type. For example: |
| * |
| * fruit::Component<const MyInterface> getMyInterfaceComponent() { |
| * static const MyImplementation my_implementation = MyImplementation(); |
| * return fruit::createComponent() |
| * .bindInstance(my_implementation) |
| * .bind<MyInterface, MyImplementation>(); |
| * } |
| * |
| * In addition to binding the type I to the type C, a `bind()` can also be used to bind a |
| * std::function<std::unique_ptr<I>(Args...)> to a std::function<std::unique_ptr<C>(Args...)> or a |
| * std::function<C(Args...)>. For example: |
| * |
| * fruit::Component<std::function<std::unique_ptr<MyInterface>(int)>> getIFactoryComponent() { |
| * static const std::function<MyImplementation(int)> cFactory = [](int n) { return MyImplementation(n); }; |
| * return fruit::createComponent() |
| * .bind<MyInterface, MyImplementation>() |
| * .bindInstance(cFactory); |
| * } |
| * |
| * Or alternatively you can do the same using constructor injection: |
| * |
| * class MyImplementation { |
| * public: |
| * INJECT(MyImplementation(ASSISTED(int) n)) |
| * : n(n) { |
| * } |
| * ... |
| * }; |
| * |
| * fruit::Component<std::function<std::unique_ptr<MyInterface>(int)>> getIFactoryComponent() { |
| * return fruit::createComponent() |
| * .bind<MyInterface, MyImplementation>(); |
| * } |
| * |
| * Fruit determines the actual binding(s) to generate based on the types you declare as provided in the returned |
| * Component<> type (e.g. in the last example std::function<std::unique_ptr<MyInterface>(int)> is declared as provided |
| * so Fruit will generate a factory binding instead of a normal MyInterface->MyImplementation binding. |
| * |
| * Fruit can also detect types that are needed for constructor/provider/factory bindings, and it will then use that |
| * information to determine the desired binding. For example: |
| * |
| * class MyImplementation { |
| * public: |
| * INJECT(MyImplementation(ASSISTED(int) n)) |
| * : n(n) { |
| * } |
| * ... |
| * }; |
| * |
| * class Foo { |
| * private: |
| * std::function<std::unique_ptr<MyInterface>(int)> factory; |
| * public: |
| * INJECT(Foo(std::function<std::unique_ptr<MyInterface>(int)> factory)) |
| * : factory(factory) { |
| * } |
| * }; |
| * |
| * fruit::Component<Foo> getIFactoryComponent() { |
| * return fruit::createComponent() |
| * // We want to bind Foo, which requires std::function<std::unique_ptr<MyInterface>(int)>. |
| * // So std::function<std::unique_ptr<MyInterface>(int)> will be bound to |
| * // std::function<std::unique_ptr<MyImplementation>(int)>, and that will be bound using constructor injection. |
| * .bind<MyInterface, MyImplementation>(); |
| * } |
| * |
| * All these cases support annotated injection, just wrap I and/or C in fruit::Annotated<> if desired. For example: |
| * |
| * struct MyAnnotation{}; |
| * |
| * fruit::Component<fruit::Annotated<MyAnnotation, MyInterface>> getMyInterfaceComponent() { |
| * return fruit::createComponent() |
| * .bind<fruit::Annotated<MyAnnotation, MyInterface>, MyImplementation>(); |
| * } |
| */ |
| template <typename I, typename C> |
| PartialComponent<fruit::impl::Bind<I, C>, Bindings...> bind(); |
| |
| /** |
| * Registers Signature as the constructor signature to use to inject a type. |
| * |
| * Example usage: |
| * |
| * fruit::createComponent() |
| * .registerConstructor<Foo(Bar*,Baz*)>() // Registers the constructor Foo::Foo(Bar*,Baz*) |
| * |
| * It's usually more convenient to use an INJECT macro or Inject typedef instead, e.g.: |
| * |
| * class Foo { |
| * public: |
| * // This also declares the constructor |
| * INJECT(Foo(Bar* bar, Baz* baz)); |
| * ... |
| * }; |
| * |
| * or (equivalent): |
| * |
| * class Foo { |
| * public: |
| * using Inject = Foo(Bar*, Baz*); |
| * Foo(Bar* bar, Baz* baz); |
| * ... |
| * }; |
| * |
| * Use registerConstructor() when you want to inject the class C in different ways in different components (just make |
| * sure those don't end up in the same injector, or use annotated injection to prevent the bindings from clashing), |
| * or when C is a third-party class that can't be modified. |
| * |
| * This supports annotated injection, just wrap the desired types (return type and/or argument types of the signature) |
| * with fruit::Annotated<> if desired. For example: |
| * |
| * struct Annotation1 {}; |
| * struct Annotation2 {}; |
| * |
| * struct Foo { |
| * Foo(Bar* bar) {...} |
| * }; |
| * |
| * fruit::Component<fruit::Annotated<Annotation1, Bar>> getBarComponent() {...} |
| * |
| * fruit::Component<fruit::Annotated<Annotation2, Foo>> getFooComponent() { |
| * return fruit::createComponent() |
| * .install(getBarComponent) |
| * .registerConstructor<fruit::Annotated<Annotation2, Foo>(fruit::Annotated<Annotation1, Bar*>)>(); |
| * } |
| * |
| * This does *not* support assisted injection, for that you should use registerFactory() instead. |
| * |
| * The allowed argument types in the signature are, for any class (or fundamental) type C: |
| * |
| * C |
| * C* |
| * C& |
| * const C* |
| * const C& |
| * shared_ptr<C> |
| * Provider<C> |
| * Provider<const C> |
| * Annotated<Annotation, C> (for any type `Annotation') |
| * Annotated<Annotation, C*> (for any type `Annotation') |
| * Annotated<Annotation, C&> (for any type `Annotation') |
| * Annotated<Annotation, const C*> (for any type `Annotation') |
| * Annotated<Annotation, const C&> (for any type `Annotation') |
| * Annotated<Annotation, shared_ptr<C>> (for any type `Annotation') |
| * Annotated<Annotation, Provider<C>> (for any type `Annotation') |
| * Annotated<Annotation, Provider<const C>> (for any type `Annotation') |
| */ |
| template <typename Signature> |
| PartialComponent<fruit::impl::RegisterConstructor<Signature>, Bindings...> registerConstructor(); |
| |
| /** |
| * Use this method to bind the type C to a specific instance. |
| * The caller must ensure that the provided reference is valid for the entire lifetime of the component and of any |
| * components or injectors that install this component; the caller must also ensure that the object is destroyed after |
| * the last components/injectors using it are destroyed. |
| * |
| * Example usage: |
| * |
| * Component<Request> getRequestComponent(Request* request) { |
| * return fruit::createComponent() |
| * .bindInstance(*request); |
| * } |
| * |
| * NormalizedComponent<...> normalizedComponent = ...; |
| * Request request; |
| * Injector<...> injector(normalizedComponent, |
| * getRequestComponent, |
| * request)); |
| * |
| * This should be used sparingly (you should let Fruit handle the object lifetime when possible), but in some cases it |
| * is necessary; for example, if a web server creates an injector to handle each request, this method can be used to |
| * inject the request itself as in the example above (see the Server page in the Fruit tutorial for more details). |
| * |
| * It's also possible to bind constants, see the documentation of the bindInstance() method taking a const& for |
| * details. |
| */ |
| template <typename C> |
| PartialComponent<fruit::impl::BindInstance<C, C>, Bindings...> bindInstance(C& instance); |
| |
| /** |
| * Similar to the previous, but binds a const&. Note that the reference must still outlive the component/injector |
| * as in the non-const case. |
| * When using this method, you must declare that the type is constant in the Component type. For example: |
| * |
| * Component<const MyExpensiveClass> getMyExpensiveClassComponent() { |
| * static const MyExpensiveClass my_expensive_class = createMyExpensiveClass(); |
| * return fruit::createComponent() |
| * .bindInstance(my_expensive_class); |
| * } |
| * |
| * Constant bindings can be used as other bindings, except that you can only inject the constant type (e.g. as a |
| * constructor parameter) as: |
| * |
| * C |
| * const C* |
| * const C& |
| * Provider<const C> |
| * Annotated<Annotation, C> (for any type `Annotation') |
| * Annotated<Annotation, const C*> (for any type `Annotation') |
| * Annotated<Annotation, const C&> (for any type `Annotation') |
| * Annotated<Annotation, Provider<const C>> (for any type `Annotation') |
| * |
| * While you can't inject it as: |
| * |
| * C* |
| * C& |
| * shared_ptr<C> |
| * Provider<C> |
| * Annotated<Annotation, C*> (for any type `Annotation') |
| * Annotated<Annotation, C&> (for any type `Annotation') |
| * Annotated<Annotation, shared_ptr<C>> (for any type `Annotation') |
| * Annotated<Annotation, Provider<C>> (for any type `Annotation') |
| */ |
| template <typename C> |
| PartialComponent<fruit::impl::BindConstInstance<C, C>, Bindings...> bindInstance(const C& instance); |
| |
| /** |
| * This is deleted to catch cases where the instance would likely be destroyed before the component/injectors. |
| */ |
| template <typename C> |
| PartialComponent<fruit::impl::BindConstInstance<C, C>, Bindings...> bindInstance(C&&) = delete; |
| |
| /** |
| * Similar to the first version of bindInstance(), but allows to specify an annotated type that |
| * will be bound to the specified value. |
| * For example, to bind an instance to the type fruit::Annotated<Hostname, std::string>, you can use: |
| * |
| * fruit::Component<fruit::Annotated<Hostname, std::string>> getHostnameComponent(std::string* hostname) { |
| * fruit::createComponent() |
| * .bindInstance<fruit::Annotated<Hostname, std::string>>(*hostname); |
| * } |
| */ |
| template <typename AnnotatedType, typename C> |
| PartialComponent<fruit::impl::BindInstance<AnnotatedType, C>, Bindings...> bindInstance(C& instance); |
| |
| /** |
| * Similar to the previous, but binds a const&. Example usage: |
| * |
| * fruit::Component<fruit::Annotated<Hostname, const std::string>> getHostnameComponent() { |
| * static const std::string hostname = determineHostname(); |
| * fruit::createComponent() |
| * .bindInstance<fruit::Annotated<Hostname, std::string>>(hostname); |
| * } |
| * |
| * See the documentation for the bindInstance() overload that takes a non-annotated const& for more details. |
| */ |
| template <typename AnnotatedType, typename C> |
| PartialComponent<fruit::impl::BindConstInstance<AnnotatedType, C>, Bindings...> bindInstance(const C& instance); |
| |
| /** |
| * This is deleted to catch cases where the instance would likely be destroyed before the component/injectors. |
| */ |
| template <typename AnnotatedType, typename C> |
| PartialComponent<fruit::impl::BindConstInstance<AnnotatedType, C>, Bindings...> bindInstance(C&& instance); |
| |
| /** |
| * Registers `provider' as a provider of C, where provider is a lambda with no captures returning either C or C* |
| * (prefer returning a C by value instead of allocating a C using `new C', to avoid the allocation). |
| * |
| * When injecting a C, the arguments of the provider will be injected and the provider will then be called to create |
| * the C instance, that will then be stored in the injector. |
| * |
| * If `provider' returns a pointer, it must be non-null; otherwise the program will abort. |
| * |
| * Example: |
| * |
| * fruit::Component<Foo> getFooComponent() { |
| * return fruit::createComponent() |
| * .install(getBarComponent) |
| * .install(getBazComponent) |
| * .registerProvider([](Bar* bar, Baz* baz) { |
| * Foo foo(bar, baz); |
| * foo.initialize(); |
| * return foo; |
| * }); |
| * } |
| * |
| * As in the previous example, it's not necessary to specify the type parameter, it will be inferred by the compiler. |
| * |
| * registerProvider() can't be called with a plain function, but you can write a lambda that wraps the function to |
| * achieve the same result. |
| * |
| * Registering stateful functors (including lambdas with captures) is NOT supported. |
| * However, you can write something like: |
| * |
| * struct Functor { |
| * Functor(int n) {...} |
| * MyClass operator()(Foo* foo) const {...} |
| * }; |
| * |
| * Component<MyClass> getMyClassComponent() { |
| * static const Functor aFunctor(42); |
| * return fruit::createComponent() |
| * .install(getFooComponent) |
| * .bindInstance(aFunctor) |
| * .registerProvider([](const Functor& functor, Foo* foo) { return functor(foo); }); |
| * } |
| */ |
| template <typename Lambda> |
| PartialComponent<fruit::impl::RegisterProvider<Lambda>, Bindings...> registerProvider(Lambda lambda); |
| |
| /** |
| * Similar to the previous version of registerProvider(), but allows to specify an annotated type |
| * for the provider. This allows to inject annotated types in the parameters and/or bind the |
| * provider to an annotated type. For example: |
| * |
| * struct MyAnnotation1 {}; |
| * struct MyAnnotation2 {}; |
| * |
| * Component<fruit::Annotated<Annotation1, Bar>> getBarComponent() {...} |
| * Component<Baz> getBazComponent() {...} |
| * |
| * fruit::Component<fruit::Annotated<Annotation2, Foo>> getFooComponent() { |
| * return fruit::createComponent() |
| * .install(getBarComponent) |
| * .install(getBazComponent) |
| * .registerProvider< |
| * fruit::Annotated<Annotation2, Foo>( |
| * fruit::Annotated<Annotation1, Bar*>, |
| * Baz*) |
| * >([](Bar* bar, Baz* baz) { |
| * Foo foo(bar, baz); |
| * foo.initialize(); |
| * return foo; |
| * }); |
| * } |
| */ |
| template <typename AnnotatedSignature, typename Lambda> |
| PartialComponent<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>, Bindings...> |
| registerProvider(Lambda lambda); |
| |
| /** |
| * Similar to bind<I, C>(), but adds a multibinding instead. |
| * |
| * Multibindings are independent from bindings; creating a binding with bind doesn't count as a multibinding, and |
| * adding a multibinding doesn't allow to inject the type (it only allows to retrieve multibindings through the |
| * getMultibindings method of the injector). |
| * |
| * Unlike bindings, where adding a the same binding twice is allowed (and ignored), adding the same multibinding |
| * multiple times will result in the creation of multiple "equivalent" instances, that will all be returned by |
| * getMultibindings(). |
| * |
| * Another difference compared with normal bindings is that this can't be used to bind a |
| * std::function<std::unique_ptr<I>(Args...)> to a std::function<std::unique_ptr<C>(Args...)> or a |
| * std::function<C(Args...)>. |
| * |
| * As bind(), this supports annotated injection, just wrap I and/or C in fruit::Annotated<> if desired. See the |
| * documentation of bind() for more details. |
| */ |
| template <typename I, typename C> |
| PartialComponent<fruit::impl::AddMultibinding<I, C>, Bindings...> addMultibinding(); |
| |
| /** |
| * Similar to bindInstance(), but adds a multibinding instead. |
| * |
| * Multibindings are independent from bindings; creating a binding with bindInstance doesn't count as a |
| * multibinding, and adding a multibinding doesn't allow to inject the type (it only allows to retrieve |
| * multibindings through the getMultibindings method of the injector). |
| * |
| * Unlike bindings, where adding a the same binding twice is allowed (and ignored), adding several multibindings for |
| * the same instance will result in duplicated values in the result of getMultibindings. |
| * |
| * Another difference compared to bindInstance() is that you can't use this to bind a const& (note that there is no |
| * overload of this method that takes a const&). |
| * |
| * This method adds a multibinding for C. If the object implements an interface I and you want to add a multibinding |
| * for that interface instead, you must cast the object to I& before passing it to this method. |
| * |
| * Note that this takes the instance by reference, not by value; it must remain valid for the entire lifetime of this |
| * component and of any injectors created from this component. |
| * |
| * Example use: |
| * |
| * class MyClass { |
| * ... |
| * }; |
| * |
| * fruit::Component<> getMyComponent() { |
| * static MyClass x = MyClass(...); |
| * static MyClass y = MyClass(...); |
| * return fruit::createComponent() |
| * .addInstanceMultibinding(x) |
| * .addInstanceMultibinding(y); |
| * } |
| * |
| * fruit::Injector<> injector(getMyComponent); |
| * // This vector contains {&x, &y}. |
| * const std::vector<MyClass*>& objects = injector.getMultibindings<MyClass>(); |
| */ |
| template <typename C> |
| PartialComponent<fruit::impl::AddInstanceMultibinding<C>, Bindings...> addInstanceMultibinding(C& instance); |
| |
| /** |
| * Similar to the previous version of addInstanceMultibinding(), but allows to specify an |
| * annotated type. |
| * Example use: |
| * |
| * struct MyAnnotation {}; |
| * |
| * class MyClass { |
| * ... |
| * }; |
| * |
| * fruit::Component<> getMyComponent() { |
| * static MyClass x = MyClass(...); |
| * static MyClass y = MyClass(...); |
| * return fruit::createComponent() |
| * .addInstanceMultibinding<fruit::Annotated<MyAnnotation, MyClass>>(x) |
| * .addInstanceMultibinding<fruit::Annotated<MyAnnotation, MyClass>>(y); |
| * } |
| * |
| * fruit::Injector<> injector(getMyComponent); |
| * // This vector contains {&x, &y}. |
| * const std::vector<MyClass*>& objects = injector.getMultibindings<fruit::Annotated<MyAnnotation, MyClass>>(); |
| */ |
| template <typename AnnotatedC, typename C> |
| PartialComponent<fruit::impl::AddInstanceMultibinding<AnnotatedC>, Bindings...> addInstanceMultibinding(C& instance); |
| |
| /** |
| * Equivalent to calling addInstanceMultibinding() for each elements of `instances'. |
| * See the documentation of addInstanceMultibinding() for more details. |
| * |
| * Note that this takes the vector by reference, not by value; the vector (and its elements) must remain valid for the |
| * entire lifetime of this component and of any injectors created from this component. |
| * |
| * Example use: |
| * |
| * class MyClass { |
| * ... |
| * }; |
| * |
| * fruit::Component<> getMyComponent() { |
| * static MyClass x = MyClass(...); |
| * static std::vector<MyClass> other_objects{MyClass(...), MyClass(...)}; |
| * return fruit::createComponent() |
| * .addInstanceMultibinding(x) |
| * .addInstanceMultibindings(other_objects); |
| * } |
| * |
| * fruit::Injector<> injector(getMyComponent); |
| * // This vector contains {&x, &(other_objects[0]), &(other_objects[1])}. |
| * const std::vector<MyClass*>& objects = injector.getMultibindings<MyClass>(); |
| */ |
| template <typename C> |
| PartialComponent<fruit::impl::AddInstanceVectorMultibindings<C>, Bindings...> |
| addInstanceMultibindings(std::vector<C>& instances); |
| |
| /** |
| * Similar to the previous version of addInstanceMultibindings(), but it allows to specify an annotated type. |
| * |
| * Example use: |
| * |
| * class MyClass { |
| * ... |
| * }; |
| * |
| * fruit::Component<> getMyComponent() { |
| * static MyClass x = MyClass(...); |
| * static std::vector<MyClass> other_objects{MyClass(...), MyClass(...)}; |
| * return fruit::createComponent() |
| * .addInstanceMultibinding<fruit::Annotated<MyAnnotation, MyClass>>(x) |
| * .addInstanceMultibindings<fruit::Annotated<MyAnnotation, MyClass>>(other_objects); |
| * } |
| * |
| * fruit::Injector<> injector(getMyComponent); |
| * // This vector contains {&x, &(other_objects[0]), &(other_objects[1])}. |
| * const std::vector<MyClass*>& objects = injector.getMultibindings<fruit::Annotated<MyAnnotation, MyClass>>(); |
| */ |
| template <typename AnnotatedC, typename C> |
| PartialComponent<fruit::impl::AddInstanceVectorMultibindings<AnnotatedC>, Bindings...> |
| addInstanceMultibindings(std::vector<C>& instances); |
| |
| /** |
| * Similar to registerProvider, but adds a multibinding instead. |
| * |
| * Multibindings are independent from bindings; creating a binding with registerProvider doesn't count as a |
| * multibinding, and adding a multibinding doesn't allow to inject the type (it only allows to retrieve multibindings |
| * through the getMultibindings method of the injector). |
| * |
| * Unlike bindings, where adding a the same binding twice is allowed (and ignored), adding the same multibinding |
| * provider multiple times will result in the creation of multiple "equivalent" instances, that will all be returned |
| * by getMultibindings. |
| * It is good practice to add the multibindings in a component that is "close" to the injector in the get*Component |
| * call chain, to avoid adding the same multibinding more than once. |
| * |
| * Example use: |
| * |
| * class MyClass { |
| * public: |
| * MyClass(int n) {...} |
| * }; |
| * |
| * fruit::Component<> getMyComponent() { |
| * return fruit::createComponent() |
| * .addMultibindingProvider([]() { return MyClass(10); }) |
| * .addMultibindingProvider([]() { return MyClass(10); }) |
| * .addMultibindingProvider([]() { return MyClass(20); }); |
| * } |
| * |
| * fruit::Injector<> injector(getMyComponent); |
| * // This vector contains {&x, &y, &z} where x and y are MyClass objects constructed with 10 and z is a MyClass |
| * // object constructed with 20. |
| * const std::vector<MyClass*>& objects = injector.getMultibindings<MyClass>(); |
| * |
| * Note that this method adds a multibinding for the type returned by the provider. If the returned object implements |
| * an interface I and you want to add a multibinding for that interface instead, you should cast the pointer to I* |
| * before returning it. |
| */ |
| template <typename Lambda> |
| PartialComponent<fruit::impl::AddMultibindingProvider<Lambda>, Bindings...> addMultibindingProvider(Lambda lambda); |
| |
| /** |
| * Similar to the previous version of addMultibindingProvider(), but allows to specify an annotated type |
| * for the provider. This allows to inject annotated types in the parameters and/or bind the |
| * provider to an annotated type. |
| * |
| * Example use: |
| * |
| * struct MyAnnotation1 {}; |
| * struct MyAnnotation2 {}; |
| * |
| * Component<fruit::Annotated<Annotation1, Bar>> getBarComponent() {...} |
| * Component<Baz> getBazComponent() {...} |
| * |
| * fruit::Component<> getFooComponent() { |
| * return fruit::createComponent() |
| * .install(getBarComponent) |
| * .install(getBazComponent) |
| * .registerMultibindingProvider< |
| * fruit::Annotated<Annotation2, Foo>( |
| * fruit::Annotated<Annotation1, Bar*>, |
| * Baz*) |
| * >([](Bar* bar, Baz* baz) { |
| * Foo foo(bar, baz); |
| * foo.initialize(); |
| * return foo; |
| * }); |
| * } |
| * |
| * |
| * fruit::Injector<> injector(getFooComponent); |
| * // This vector contains {&x} where x is an instance of Foo constructed using the lambda above, with injected |
| * // instances of Bar and Baz. |
| * const std::vector<MyClass*>& objects = injector.getMultibindings<fruit::Annotated<Annotation2, Foo>>(); |
| */ |
| template <typename AnnotatedSignature, typename Lambda> |
| PartialComponent<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>, Bindings...> |
| addMultibindingProvider(Lambda lambda); |
| |
| /** |
| * Registers `factory' as a factory of C, where `factory' is a lambda with no captures returning C. |
| * This is typically used for assisted injection (but it can also be used if no parameters are assisted). |
| * |
| * C can be any class (or fundamental) type. If C is std::unique_ptr<T>, the factory together with a bind<I,C> in the |
| * same component will automatically bind the corresponding std::function that returns a std::unique_ptr<I>. |
| * See the documentation of bind() for more details. |
| * |
| * The returned type can't be a pointer type. If you don't want to return it by value, you should return a |
| * std::unique_ptr instead. |
| * |
| * Example: |
| * |
| * Component<std::function<std::unique_ptr<MyClass>(int)>> getMyClassComponent() { |
| * fruit::createComponent() |
| * .install(getFooComponent) |
| * .registerFactory<std::unique_ptr<MyClass>(Foo*, fruit::Assisted<int>)>( |
| * [](Foo* foo, int n) { |
| * return std::unique_ptr<MyClass>(new MyClass(foo, n)); |
| * }); |
| * } |
| * |
| * Injector<std::function<std::unique_ptr<MyClass>(int)>> injector(getMyClassComponent); |
| * |
| * std::function<std::unique_ptr<MyClass>(int)> factory(injector); |
| * std::unique_ptr<MyClass> x = factory(42); |
| * |
| * The parameters marked as Assisted will become parameters of the std::function (in the same order), while the others |
| * (e.g. Foo in the example above) will be injected. |
| * |
| * Unlike registerProvider(), where the signature is inferred, for this method the signature (including any Assisted |
| * annotations) must be specified explicitly, while the second template parameter is inferred. |
| * |
| * If the only thing that the factory does is to call new and the constructor of the class, it's usually more |
| * convenient to use an Inject typedef or INJECT macro instead, e.g. the following are equivalent to the above: |
| * |
| * class MyClass { |
| * public: |
| * using Inject = MyClass(Foo*, Assisted<int>); |
| * |
| * MyClass(Foo* foo, int n) {...} |
| * }; |
| * |
| * or: |
| * |
| * class MyClass { |
| * public: |
| * INJECT(MyClass(Foo* foo, ASSISTED(int) n)) {...} |
| * }; |
| * |
| * Use registerFactory() when you want to inject the class in different ways in different components (just make sure |
| * those don't end up in the same injector), or when MyClass is a third-party class that can't be modified. |
| * |
| * registerFactory() can't be called with a plain function, but you can write a lambda that wraps the function to |
| * achieve the same result. |
| * |
| * Registering stateful functors (including lambdas with captures) is NOT supported. |
| * However, you can write something like: |
| * |
| * struct Functor { |
| * Functor(float x) {...} |
| * std::unique_ptr<MyClass> operator()(Foo* foo, int n) {...} |
| * }; |
| * |
| * Component<std::function<std::unique_ptr<MyClass>(int)>> getMyClassComponent() { |
| * static const Functor aFunctor(42.0); |
| * return fruit::createComponent() |
| * ... // Bind Foo |
| * .bindInstance(aFunctor) |
| * .registerFactory< |
| * std::unique_ptr<MyClass>( |
| * Functor functor, |
| * Foo*, |
| * Assisted<int>) |
| * >([](Functor functor, Foo* foo, int n) { |
| * return functor(foo, n); |
| * }); |
| * } |
| */ |
| template <typename DecoratedSignature, typename Factory> |
| PartialComponent<fruit::impl::RegisterFactory<DecoratedSignature, Factory>, Bindings...> |
| registerFactory(Factory factory); |
| |
| /** |
| * Adds the bindings (and multibindings) in the Component obtained by calling fun(args...) to the current component. |
| * |
| * For example, these component functions: |
| * fruit::Component<Foo> getComponent1(); |
| * fruit::Component<Bar> getComponent2(int n, std::string s); |
| * |
| * can be combined as: |
| * |
| * fruit::Component<Foo, Bar> getFooBarComponent() { |
| * return fruit::createComponent() |
| * .install(getComponent1) |
| * .install(getComponent2, 5, std::string("Hello")); |
| * } |
| * |
| * If any `args` are provided, they must be: |
| * - Copy-constructible |
| * - Move-constructible |
| * - Assignable |
| * - Move-assignable |
| * - Equality comparable (i.e., operator== must be defined for two values of that type) |
| * - Hashable (i.e., std::hash must be defined for values of that type) |
| * |
| * Note that this only applies to `args`. E.g. in the example above `int` and `std::string` must satisfy this |
| * requirement (and they do), but `Foo` and `Bar` don't need to. |
| * |
| * 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. |
| * |
| * A lambda with no captures can also be used as the first argument, for example: |
| * |
| * fruit::Component<Foo, Bar> getFooBarComponent() { |
| * return fruit::createComponent() |
| * .install([]() { return getComponent1(); }) |
| * .install([](int n) { return getComponent2(n, std::string("Hello")); }, 5); |
| * } |
| * |
| * These two install() calls are equivalent to the previous ones. |
| * |
| * As in the example, the template parameters for this method will be inferred by the compiler, it's not necessary to |
| * specify them explicitly. |
| * |
| * Fruit automatically de-duplicates install() calls, so they're effectively memoized (within each injector). |
| * For example, in this code: |
| * |
| * fruit::Component<Foo> getFooComponent() {...} |
| * |
| * fruit::Component<Bar> getBarComponent() { |
| * return fruit::createComponent() |
| * .install(getFooComponent) |
| * .bind<Bar, BarImpl>(); |
| * } |
| * |
| * fruit::Component<Baz> getBazComponent() { |
| * return fruit::createComponent() |
| * .install(getFooComponent) |
| * .bind<Baz, BazImpl>(); |
| * } |
| * |
| * fruit::Component<Bar, Baz> getBarBazComponent() { |
| * return fruit::createComponent() |
| * .install(getBarComponent) |
| * .install(getBazComponent); |
| * } |
| * |
| * fruit::Injector<Bar, Baz> injector(getBarBazComponent); |
| * |
| * |
| * getFooComponent() will only be called once. |
| * For Component functions with arguments, only one call will be done for each set of arguments, but multiple calls |
| * might be made if multiple sets of arguments are used. |
| * |
| * If you actually want a Component function to be called/installed multiple times (e.g. if it binds a multibinding |
| * and you actually want multiple multibindings to be bound) you can add a dummy argument and specify different values |
| * for that argument when installing the component. |
| */ |
| template <typename... OtherComponentParams, typename... FormalArgs, typename... Args> |
| PartialComponent<fruit::impl::InstallComponent<fruit::Component<OtherComponentParams...>(FormalArgs...)>, Bindings...> |
| install(fruit::Component<OtherComponentParams...> (*)(FormalArgs...), Args&&... args); |
| |
| /** |
| * Similar to install(), but allows to install a variable number of component functions instead of just 1. This |
| * additional flexibility is sometimes useful in templated `get*Component` functions and for other advanced use-cases. |
| * |
| * To use this method, wrap each get*Component function with its args in a fruit::ComponentFunction<...> object (using |
| * the helper function fruit::componentFunction), then pass all the fruit::ComponentFunction<...> objects (which can |
| * potentially have different params) to this method. |
| * |
| * For example: |
| * |
| * fruit::Component<Foo, Bar> getBarBazComponent() { |
| * return fruit::createComponent() |
| * .installComponentFunctions( |
| * fruit::componentFunction(getFooComponent, a, b, c), |
| * fruit::componentFunction(getBarComponent, x, y)); |
| * } |
| * |
| * Is equivalent to: |
| * |
| * fruit::Component<Foo, Bar> getBarBazComponent() { |
| * return fruit::createComponent() |
| * .install(getFooComponent, a, b, c) |
| * .install(getBarComponent, x, y); |
| * } |
| * |
| * This is a simple example to show the idea, however in a simple case like this it's easier to just use install(). |
| */ |
| template <typename... ComponentFunctions> |
| PartialComponent<fruit::impl::InstallComponentFunctions<ComponentFunctions...>, Bindings...> |
| installComponentFunctions(ComponentFunctions... componentFunctions); |
| |
| /** |
| * This class is returned by PartialComponent::replace, see the documentation of that method for more information. |
| */ |
| template <typename ReplacedComponent, typename... GetReplacedComponentFormalArgs> |
| class PartialComponentWithReplacementInProgress { |
| private: |
| using storage_t = fruit::impl::PartialComponentStorage< |
| fruit::impl::PartialReplaceComponent<ReplacedComponent(GetReplacedComponentFormalArgs...)>, Bindings...>; |
| |
| public: |
| template <typename... FormalArgs, typename... Args> |
| PartialComponent<fruit::impl::ReplaceComponent<ReplacedComponent(GetReplacedComponentFormalArgs...), |
| ReplacedComponent(FormalArgs...)>, |
| Bindings...> |
| with(ReplacedComponent (*)(FormalArgs...), Args&&... args); |
| |
| PartialComponentWithReplacementInProgress(storage_t storage) // NOLINT(google-explicit-constructor) |
| : storage(storage) {} |
| |
| private: |
| storage_t storage; |
| |
| PartialComponentWithReplacementInProgress() = delete; |
| }; |
| |
| /** |
| * This allows to replace an installed Component with another one. This is useful for testing. |
| * For example, if you have these components: |
| * |
| * fruit::Component<MyDependency> getDependencyComponent() {...} |
| * |
| * fruit::Component<Foo> getFooComponent() { |
| * return fruit::createComponent() |
| * .install(getDependencyComponent) |
| * .bind<Foo, FooImpl>(); |
| * } |
| * |
| * fruit::Component<Bar> getBarComponent() { |
| * return fruit::createComponent() |
| * .install(getFooComponent) |
| * .bind<Bar, BarImpl>(); |
| * } |
| * |
| * When you test Bar, you might want to replace getDependencyComponent with a component that binds a fake |
| * MyDependency: |
| * |
| * fruit::Component<MyDependency> getFakeDependencyComponent() {...} |
| * |
| * To do so, you can define a component like: |
| * |
| * fruit::Component<Bar> getBarComponentWithFakeDependency() { |
| * return fruit::createComponent() |
| * .replace(getDependencyComponent).with(getFakeDependencyComponent) |
| * .install(getBarComponent); |
| * } |
| * |
| * This component is equivalent to: |
| * |
| * fruit::Component<Bar> getBarComponentWithFakeDependency() { |
| * return fruit::createComponent() |
| * .install(getFakeDependencyComponent) |
| * .bind<Foo, FooImpl>() |
| * .bind<Bar, BarImpl>(); |
| * } |
| * |
| * However this way you don't need to duplicate the bindings for Foo and Bar, and you don't even need to include them |
| * in the translation unit (i.e., cc/cpp file) that defines getBarComponentWithFakeDependency(). |
| * In codebases with many layers, this can save a lot of duplication. |
| * |
| * Note that the .replace(...).with(...) must appear *before* installing the component to which it's applied to; |
| * e.g., in the example above note how we install getBarComponent after the replacement in |
| * getBarComponentWithFakeDependency. |
| * If you add a replacement after the replaced component has been installed, Fruit will report an error at run-time. |
| * |
| * In the example above, the replaced and replacement component functions had no arguments, however it's also possible |
| * to replace component functions with args. The arguments of the replaced and replacement component functions are |
| * independent; for example .replace(getDependencyComponentWithArgs, 15).with(myFakeComponentWithNoArgs) is allowed |
| * and it would replace all install(getDependencyComponentWithArgs, 15) calls with install(myFakeComponentWithNoArgs). |
| * |
| * The component types returned by the replaced and replacement components must be the same. For example, this is NOT |
| * allowed: |
| * |
| * fruit::Component<MyDependency, SomethingElse> getFakeDependencyComponentWithSomethingElse() {...} |
| * |
| * fruit::Component<Bar> getBarComponentWithFakeDependency() { |
| * return fruit::createComponent() |
| * .replace(getDependencyComponent).with(getFakeDependencyComponentWithSomethingElse) // error! |
| * .install(getBarComponent); |
| * } |
| * |
| * But replacing a replaced component is allowed: |
| * |
| * fruit::Component<MyDependency> getOtherFakeDependencyComponent() {...} |
| * |
| * fruit::Component<Bar> getBarComponentWithOtherFakeDependency() { |
| * return fruit::createComponent() |
| * // The two replacements can appear in any order, but they must both be before the install(). |
| * .replace(getFakeDependencyComponent).with(getOtherFakeDependencyComponent) |
| * .replace(getDependencyComponent).with(getFakeDependencyComponent) |
| * .install(getBarComponent); |
| * } |
| * |
| * Of course this is a simple example, in the real world the replacements and the install would probably come from |
| * other components. |
| * |
| * And note that you can also replace components that define replacements, for example: |
| * |
| * fruit::Component<> getFakeDependencyReplacementComponent() { |
| * return fruit::createComponent() |
| * .replace(getDependencyComponent).with(getFakeDependencyComponentWithSomethingElse); |
| * } |
| * |
| * fruit::Component<...> getComponent() { |
| * return fruit::createComponent() |
| * .replace(getFakeDependencyReplacementComponent).with(...) |
| * .install(...); |
| * } |
| * |
| * Replacements are only installed if the replaced component is installed, otherwise they are ignored. |
| * In the first example above, if getFooComponent didn't install getDependencyComponent, when a test creates an |
| * injector for getBarComponentWithFakeDependency it would not install getFakeDependencyComponent. |
| */ |
| template <typename... OtherComponentParams, typename... FormalArgs, typename... Args> |
| typename PartialComponent<Bindings...>::template PartialComponentWithReplacementInProgress< |
| fruit::Component<OtherComponentParams...>, FormalArgs...> |
| replace(fruit::Component<OtherComponentParams...> (*)(FormalArgs...), Args&&... args); |
| |
| ~PartialComponent() = default; |
| |
| // Do not use. Use fruit::createComponent() instead. |
| PartialComponent() = delete; |
| |
| // Do not use. Only use PartialComponent for temporaries, and then convert it to a Component. |
| PartialComponent(const PartialComponent&) = delete; |
| PartialComponent(PartialComponent&&) = delete; |
| |
| private: |
| template <typename... OtherBindings> |
| friend class PartialComponent; |
| |
| template <typename... Types> |
| friend class Component; |
| |
| fruit::impl::PartialComponentStorage<Bindings...> storage; |
| |
| PartialComponent(fruit::impl::PartialComponentStorage<Bindings...> storage); // NOLINT(google-explicit-constructor) |
| |
| template <typename NewBinding> |
| using OpFor = typename fruit::impl::meta::OpForComponent<Bindings...>::template AddBinding<NewBinding>; |
| |
| friend PartialComponent<> createComponent(); |
| }; |
| |
| } // namespace fruit |
| |
| #include <fruit/impl/component.defn.h> |
| |
| #endif // FRUIT_COMPONENT_H |