12#ifndef ARCCORE_BASE_INTERNAL_DEPENDENCYINJECTION_H
13#define ARCCORE_BASE_INTERNAL_DEPENDENCYINJECTION_H
22#include "arccore/base/ExternalRef.h"
23#include "arccore/base/GenericRegisterer.h"
27#include "arccore/base/NotImplementedException.h"
42namespace Arcane::DependencyInjection
47namespace Arcane::DependencyInjection::impl
51class IInstanceFactory;
52template <
typename InterfaceType>
54class ConcreteFactoryTypeInfo;
62namespace Arcane::DependencyInjection
68class ARCCORE_BASE_EXPORT IInjectedInstance
72 virtual ~IInjectedInstance() =
default;
73 virtual bool hasName(
const String& str)
const = 0;
74 virtual bool hasTypeInfo(
const std::type_info& tinfo)
const = 0;
85class ARCCORE_BASE_EXPORT ProviderProperty
89 ProviderProperty(
const char* name)
95 const char* name()
const {
return m_name; }
110namespace Arcane::DependencyInjection::impl
120 TypeInfo(
const TraceInfo& trace_info,
const std::type_info& type_info)
121 : m_trace_info(trace_info)
122 , m_type_info(type_info)
127 template <
typename Type>
static TypeInfo create()
129 return TypeInfo(A_FUNCINFO,
typeid(
Type));
131 const TraceInfo& traceInfo()
const {
return m_trace_info; }
132 const std::type_info& stdTypeInfo()
const {
return m_type_info; }
136 TraceInfo m_trace_info;
137 const std::type_info& m_type_info;
150class ARCCORE_BASE_EXPORT ConcreteFactoryTypeInfo
154 ConcreteFactoryTypeInfo(TypeInfo&& a, TypeInfo&& b, TypeInfo&& c)
155 : m_interface_info(a)
157 , m_constructor_info(c)
162 template <
typename InterfaceType,
typename ConcreteType,
typename ConstructorType>
163 static ConcreteFactoryTypeInfo create()
165 return ConcreteFactoryTypeInfo(TypeInfo::create<InterfaceType>(),
166 TypeInfo::create<ConcreteType>(),
167 TypeInfo::create<ConstructorType>());
169 const TypeInfo& interfaceTypeInfo()
const {
return m_interface_info; }
170 const TypeInfo& concreteTypeInfo()
const {
return m_concrete_info; }
171 const TypeInfo& constructorTypeInfo()
const {
return m_constructor_info; }
175 TypeInfo m_interface_info;
176 TypeInfo m_concrete_info;
177 TypeInfo m_constructor_info;
187template <
typename InterfaceType>
188class IInjectedRefInstanceT
189:
public IInjectedInstance
193 virtual Ref<InterfaceType> instance() = 0;
205template <
typename InterfaceType>
206class InjectedRefInstance
207:
public IInjectedRefInstanceT<InterfaceType>
211 using InstanceType = Ref<InterfaceType>;
215 InjectedRefInstance(InstanceType t_instance,
const String& t_name)
216 : m_instance(t_instance)
222 Ref<InterfaceType> instance()
override {
return m_instance; }
223 bool hasName(
const String& str)
const override {
return m_name == str; }
224 bool hasTypeInfo(
const std::type_info& tinfo)
const override {
return typeid(InstanceType) == tinfo; }
228 InstanceType m_instance;
239template <
typename Type>
240class IInjectedValueInstance
241:
public IInjectedInstance
245 virtual Type instance()
const = 0;
255template <
typename Type>
256class InjectedValueInstance
257:
public IInjectedValueInstance<Type>
261 using InstanceType =
Type;
265 InjectedValueInstance(
Type t_instance,
const String& t_name)
266 : m_instance(t_instance)
272 Type instance()
const override {
return m_instance; }
273 bool hasName(
const String& str)
const override {
return m_name == str; }
274 bool hasTypeInfo(
const std::type_info& tinfo)
const override {
return typeid(InstanceType) == tinfo; }
291class ARCCORE_BASE_EXPORT InjectedInstanceRef
293 typedef Ref<IInjectedInstance> RefType;
297 explicit InjectedInstanceRef(
const RefType& r)
303 InjectedInstanceRef() =
default;
307 static InjectedInstanceRef
createRef(IInjectedInstance* p)
309 return InjectedInstanceRef(RefType::create(p));
311 static InjectedInstanceRef createRefNoDestroy(IInjectedInstance* p)
313 return InjectedInstanceRef(RefType::_createNoDestroy(p));
315 static InjectedInstanceRef createWithHandle(IInjectedInstance* p, Internal::ExternalRef handle)
317 return InjectedInstanceRef(RefType::createWithHandle(p, handle));
322 IInjectedInstance* get()
const {
return m_instance.get(); }
323 void reset() { m_instance.reset(); }
337class ARCCORE_BASE_EXPORT IInstanceFactory
343 virtual ~IInstanceFactory() =
default;
347 virtual InjectedInstanceRef createGenericReference(Injector& injector,
const String& name) = 0;
348 virtual const FactoryInfoImpl* factoryInfoImpl()
const = 0;
349 virtual ConcreteFactoryTypeInfo concreteFactoryInfo()
const = 0;
350 virtual Int32 nbConstructorArg()
const = 0;
360class ARCCORE_BASE_EXPORT FactoryInfo
362 friend class Arcane::DependencyInjection::Injector;
366 explicit FactoryInfo(
const ProviderProperty& property);
370 static FactoryInfo create(
const ProviderProperty& property,
371 [[maybe_unused]]
const char* file_name,
372 [[maybe_unused]]
int line_number)
374 return FactoryInfo(property);
376 void addFactory(Ref<IInstanceFactory> f);
377 bool hasName(
const String& str)
const;
378 const FactoryInfoImpl* _impl()
const {
return m_p.get(); }
382 std::shared_ptr<FactoryInfoImpl> m_p;
394class ARCCORE_BASE_EXPORT AbstractInstanceFactory
395:
public ReferenceCounterImpl
396,
public IInstanceFactory
404template <
typename InterfaceType>
406:
public AbstractInstanceFactory
414 InstanceFactory(
const FactoryInfoImpl* si, IConcreteFactory<InterfaceType>* sub_factory)
415 : m_factory_info_impl(si)
416 , m_sub_factory(sub_factory)
420 ~InstanceFactory()
override
422 delete m_sub_factory;
425 InjectedInstanceRef createGenericReference(Injector& injector,
const String& name)
override
427 return _create(_createReference(injector), name);
430 Ref<InterfaceType> createReference(Injector& injector)
432 return _createReference(injector);
435 const FactoryInfoImpl* factoryInfoImpl()
const override
437 return m_factory_info_impl;
440 ConcreteFactoryTypeInfo concreteFactoryInfo()
const override
442 return m_sub_factory->concreteFactoryInfo();
445 Int32 nbConstructorArg()
const override
447 return m_sub_factory->nbConstructorArg();
452 const FactoryInfoImpl* m_factory_info_impl =
nullptr;
453 IConcreteFactory<InterfaceType>* m_sub_factory =
nullptr;
457 Ref<InterfaceType> _createReference(Injector& injector)
459 return m_sub_factory->createReference(injector);
462 InjectedInstanceRef _create(Ref<InterfaceType> it,
const String& name)
464 IInjectedInstance* x = (!it) ?
nullptr : new InjectedRefInstance<InterfaceType>(it, name);
465 return InjectedInstanceRef::createRef(x);
472class ARCCORE_BASE_EXPORT IConcreteFactoryBase
476 virtual ~IConcreteFactoryBase() =
default;
480 virtual ConcreteFactoryTypeInfo concreteFactoryInfo()
const = 0;
481 virtual Int32 nbConstructorArg()
const = 0;
492template <
typename InterfaceType>
494:
public IConcreteFactoryBase
498 virtual ~IConcreteFactory() =
default;
503 virtual Ref<InterfaceType> createReference(Injector&) = 0;
509class ARCCORE_BASE_EXPORT GlobalRegisterer
510:
public GenericRegisterer<GlobalRegisterer>
512 using BaseClass = GenericRegisterer<GlobalRegisterer>;
513 static BaseClass::Info m_global_registerer_info;
517 static GenericRegisterer<GlobalRegisterer>::Info& registererInfo()
519 return m_global_registerer_info;
524 typedef FactoryInfo (*FactoryCreateFunc)(
const ProviderProperty& property);
533 GlobalRegisterer(FactoryCreateFunc func,
const ProviderProperty& property)
noexcept;
537 FactoryCreateFunc infoCreatorWithPropertyFunction() {
return m_factory_create_func; }
540 const char* name() {
return m_name; }
542 const ProviderProperty& property()
const {
return m_factory_property; }
546 FactoryCreateFunc m_factory_create_func =
nullptr;
547 const char* m_name =
nullptr;
548 ProviderProperty m_factory_property;
558namespace Arcane::DependencyInjection
567class ARCCORE_BASE_EXPORT Injector
570 using FactoryFilterFunc = bool (*)(impl::IInstanceFactory*);
572 template <
class Type>
577 static IInjectedInstance* bind(
const Type& t,
const String& name)
579 return new impl::InjectedValueInstance<Type>(t, name);
581 static Type get(Injector& i,
const String& name)
583 return i._getValue<
Type>(name);
588 template <
class Po
interType>
589 class InjectorHelper<Ref<PointerType>>
593 using ThatType = Ref<PointerType>;
597 static IInjectedInstance* bind(
const ThatType& t,
const String& name)
599 return new impl::InjectedRefInstance<PointerType>(t, name);
601 static ThatType get(Injector& i,
const String& name)
603 return i._getRef<PointerType>(name);
610 class IFactoryVisitorFunctor
614 virtual ~IFactoryVisitorFunctor() =
default;
615 virtual bool execute(impl::IInstanceFactory* f) = 0;
618 template <
typename Lambda>
class FactoryVisitorFunctor
619 :
public IFactoryVisitorFunctor
623 FactoryVisitorFunctor(Lambda& lambda)
629 virtual bool execute(impl::IInstanceFactory* f) {
return m_lambda(f); }
639 class IInstanceVisitorFunctor
643 virtual ~IInstanceVisitorFunctor() =
default;
644 virtual bool execute(IInjectedInstance* v) = 0;
647 template <
typename Lambda>
class InstanceVisitorFunctor
648 :
public IInstanceVisitorFunctor
652 InstanceVisitorFunctor(Lambda& lambda)
658 virtual bool execute(IInjectedInstance* v) {
return m_lambda(v); }
668 Injector(
const Injector&) =
delete;
669 Injector& operator=(
const Injector&) =
delete;
674 template <
typename Type>
void
675 bind(
Type iref,
const String& name = String())
677 _add(InjectorHelper<Type>::bind(iref, name));
680 template <
typename Type>
Type
681 get(
const String& name = String())
683 return InjectorHelper<Type>::get(*
this, name);
699 template <
typename InterfaceType> Ref<InterfaceType>
700 createInstance(
const String& implementation_name,
bool allow_null =
false)
702 using FactoryType = impl::InstanceFactory<InterfaceType>;
703 Ref<InterfaceType> instance;
704 auto f = [&](impl::IInstanceFactory* v) ->
bool {
705 auto* t =
dynamic_cast<FactoryType*
>(v);
708 Ref<InterfaceType> x = t->createReference(*
this);
716 FactoryVisitorFunctor ff(f);
717 _iterateFactories(implementation_name, &ff);
718 if (instance.get() || allow_null)
724 auto filter_func = [](impl::IInstanceFactory* v) ->
bool {
725 return dynamic_cast<FactoryType*
>(v) !=
nullptr;
727 _printValidImplementationAndThrow(A_FUNCINFO, implementation_name, filter_func);
730 String printFactories()
const;
732 void fillWithGlobalFactories();
740 void _add(IInjectedInstance* instance);
743 void _iterateInstances(
const std::type_info& t_info,
const String& instance_name,
744 IInstanceVisitorFunctor* lambda);
745 size_t _nbValue()
const;
746 IInjectedInstance* _value(
size_t i)
const;
756 void _iterateFactories(
const String& factory_name, IFactoryVisitorFunctor* functor)
const;
757 size_t _nbFactory()
const;
758 impl::IInstanceFactory* _factory(
size_t i)
const;
761 template <
typename InterfaceType> Ref<InterfaceType>
762 _getRef(
const String& instance_name)
764 using InjectedType = impl::IInjectedRefInstanceT<InterfaceType>;
765 InjectedType* t =
nullptr;
766 auto f = [&](IInjectedInstance* v) ->
bool {
767 t =
dynamic_cast<InjectedType*
>(v);
770 InstanceVisitorFunctor ff(f);
771 _iterateInstances(
typeid(Ref<InterfaceType>), instance_name, &ff);
773 return t->instance();
775 ARCCORE_THROW(NotImplementedException,
"Create Ref<InterfaceType> from factory");
778 template <
typename Type>
Type
779 _getValue(
const String& instance_name)
781 using InjectedType = impl::IInjectedValueInstance<Type>;
782 InjectedType* t =
nullptr;
783 auto f = [&](IInjectedInstance* v) ->
bool {
784 t =
dynamic_cast<InjectedType*
>(v);
787 InstanceVisitorFunctor ff(f);
788 _iterateInstances(
typeid(
Type), instance_name, &ff);
790 return t->instance();
791 _doError(A_FUNCINFO,
"Can not find value for type");
793 [[noreturn]]
void _printValidImplementationAndThrow(
const TraceInfo& ti,
794 const String& implementation_name,
795 FactoryFilterFunc filter_func);
796 [[noreturn]]
void _doError(
const TraceInfo& ti,
const String& message);
804namespace Arcane::DependencyInjection::impl
810class ARCCORE_BASE_EXPORT ConstructorRegistererBase
814 [[noreturn]]
void _doError1(
const String& message,
int nb_value);
823template <
typename... Args>
824class ConstructorRegisterer
825:
public ConstructorRegistererBase
829 using ArgsType = std::tuple<Args...>;
831 ConstructorRegisterer() {}
834 template <std::
size_t I>
835 static auto _get(Injector& i) -> std::tuple_element_t<I, ArgsType>
837 using SelectedType = std::tuple_element_t<I, ArgsType>;
839 return i.get<SelectedType>();
842 ArgsType createTuple(Injector& i)
845 constexpr int tuple_size = std::tuple_size<ArgsType>();
846 static_assert(tuple_size < 3,
"Too many arguments for createTuple (max=2)");
847 if constexpr (tuple_size == 0) {
850 else if constexpr (tuple_size == 1) {
851 return ArgsType(_get<0>(i));
853 else if constexpr (tuple_size == 2) {
854 return ArgsType(_get<0>(i), _get<1>(i));
857 _doError1(
"Too many arguments for createTuple n={0} max=2", tuple_size);
869template <
typename InterfaceType,
typename ConcreteType,
typename ConstructorType>
873 using Args =
typename ConstructorType::ArgsType;
877 Ref<InterfaceType> createReference(Injector& injector)
override
880 ConcreteType* st = _create(ct.createTuple(injector));
881 return makeRef<InterfaceType>(st);
883 ConcreteFactoryTypeInfo concreteFactoryInfo()
const override
885 return ConcreteFactoryTypeInfo::create<InterfaceType, ConcreteType, ConstructorType>();
887 Int32 nbConstructorArg()
const override
889 return std::tuple_size<Args>();
899 ConcreteType* _create(
const Args&& tuple_args)
901 ConcreteType* st = std::apply([](
auto&&... args) -> ConcreteType* {
return new ConcreteType(args...); }, tuple_args);
914template <
typename... Interfaces>
915class InterfaceListRegisterer
925 template <
typename ConcreteType,
typename ConstructorType>
void
926 registerFactory(FactoryInfo& si)
928 _registerFactory<ConcreteType, ConstructorType, Interfaces...>(si);
933 template <
typename ConcreteType,
typename ConstructorType,
934 typename InterfaceType,
typename... OtherInterfaces>
936 _registerFactory(FactoryInfo& fi)
938 auto* factory =
new ConcreteFactory<InterfaceType, ConcreteType, ConstructorType>();
939 fi.addFactory(createRef<InstanceFactory<InterfaceType>>(fi._impl(), factory));
941 if constexpr (
sizeof...(OtherInterfaces) > 0)
942 _registerFactory<ConcreteType, ConstructorType, OtherInterfaces...>(fi);
955template <
typename ConcreteType,
typename InterfaceList>
956class InjectionRegisterer
961 template <
typename... Constructors>
void
962 registerProviderInfo(FactoryInfo& si,
const Constructors&... args)
964 _create(si, args...);
970 InterfaceList m_interface_list;
975 template <
typename ConstructorType>
void
976 _create(FactoryInfo& si,
const ConstructorType&)
978 m_interface_list.template registerFactory<ConcreteType, ConstructorType>(si);
982 template <
typename C1,
typename C2,
typename... OtherConstructors>
983 void _create(FactoryInfo& si,
const C1& c1,
const C2& c2,
const OtherConstructors&... args)
987 _create<C2, OtherConstructors...>(si, c2, args...);
999#define ARCANE_DI_CONSTRUCTOR(...) \
1000 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<__VA_ARGS__>()
1002#define ARCANE_DI_EMPTY_CONSTRUCTOR(...) \
1003 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<>()
1007#define ARCANE_DI_INTERFACES(...) \
1008 ::Arcane::DependencyInjection::impl::InterfaceListRegisterer<__VA_ARGS__>
1010#define ARCANE_DI_REGISTER_PROVIDER(t_class, t_provider_property, t_interfaces, ...) \
1013 Arcane::DependencyInjection::impl::FactoryInfo \
1014 ARCCORE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class)(const Arcane::DependencyInjection::ProviderProperty& property) \
1016 auto si = Arcane::DependencyInjection::impl::FactoryInfo::create(property, __FILE__, __LINE__); \
1017 Arcane::DependencyInjection::impl::InjectionRegisterer<t_class, t_interfaces> injection_registerer; \
1018 injection_registerer.registerProviderInfo(si, __VA_ARGS__); \
1022 Arcane::DependencyInjection::impl::GlobalRegisterer ARCCORE_EXPORT ARCCORE_JOIN_WITH_LINE(globalServiceRegisterer##aclass)(&ARCCORE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class), t_provider_property)
#define ARCCORE_THROW(exception_class,...)
Macro to throw an exception with formatting.
#define ARCCORE_DECLARE_REFERENCE_COUNTED_INCLASS_METHODS()
Macro to declare the virtual methods managing reference counters.
#define ARCCORE_DECLARE_REFERENCE_COUNTED_CLASS(class_name)
Macro to declare that a class uses a reference counter.
#define ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS()
Macro to define methods managing counters of references.
Management of references to a C++ class.
Unicode character string.
Ref< TrueType > createRef(Args &&... args)
Creates an instance of type TrueType with arguments Args and returns a reference to it.