9#include <userver/compiler/demangle.hpp>
10#include <userver/components/component_fwd.hpp>
11#include <userver/components/raw_component_base.hpp>
12#include <userver/engine/task/task_processor_fwd.hpp>
13#include <userver/utils/impl/internal_tag.hpp>
21USERVER_NAMESPACE_BEGIN
23namespace engine::impl {
32class ComponentContextImpl;
36constexpr auto NameFromComponentType() ->
decltype(std::string_view{T::kName}) {
40template <
class T,
class... Args>
41constexpr auto NameFromComponentType(Args...) {
44 "Component does not have a 'kName' member convertible to "
45 "std::string_view. You have to explicitly specify the name: "
46 "context.FindComponent<T>(name) or "
47 "context.FindComponentOptional<T>(name)."
49 return std::string_view{};
58 ComponentsLoadCancelledException();
59 explicit ComponentsLoadCancelledException(std::string_view message);
75class ComponentContext
final {
77 ComponentContext(ComponentContext&&) =
delete;
78 ComponentContext& operator=(ComponentContext&&) =
delete;
93 return FindComponent<T>(impl::NameFromComponentType<T>());
98 T& FindComponent(std::string_view name)
const {
99 if (!Contains(name)) {
100 ThrowNonRegisteredComponent(name,
compiler::GetTypeName<T>());
103 auto* component_base = DoFindComponent(name);
104 T* ptr =
dynamic_cast<T*>(component_base);
106 ThrowComponentTypeMismatch(name,
compiler::GetTypeName<T>(), component_base);
112 template <
typename T>
113 T& FindComponent(std::string_view = {}) {
114 return ReportMisuse<T>();
119 template <
typename T>
121 return FindComponentOptional<T>(impl::NameFromComponentType<T>());
125 template <
typename T>
126 T* FindComponentOptional(std::string_view name)
const {
127 if (!Contains(name)) {
130 return dynamic_cast<T*>(DoFindComponent(name));
133 template <
typename T>
134 T& FindComponentOptional(std::string_view = {}) {
135 return ReportMisuse<T>();
141 template <
typename T>
142 engine::TaskProcessor& GetTaskProcessor(
const T&) {
143 return ReportMisuse<T>();
158 utils::impl::InternalTag,
159 impl::ComponentContextImpl& impl,
160 impl::ComponentInfo& component_info
164 impl::ComponentContextImpl& GetImpl(
utils::impl::InternalTag)
const;
167 const impl::Manager& GetManager(
utils::impl::InternalTag)
const;
173 bool Contains(std::string_view name)
const noexcept;
175 template <
typename T>
176 bool Contains(
const T&) {
177 return ReportMisuse<T>();
181 decltype(
auto) ReportMisuse() {
184 "components::ComponentContext should be accepted by "
185 "a constant reference, i.e. "
186 "`MyComponent(const components::ComponentConfig& config, "
187 "const components::ComponentContext& context)`"
192 [[noreturn]]
void ThrowNonRegisteredComponent(std::string_view name, std::string_view type)
const;
195 ThrowComponentTypeMismatch(std::string_view name, std::string_view type,
RawComponentBase* component)
const;
199 impl::ComponentContextImpl& impl_;
200 impl::ComponentInfo& component_info_;