12#ifndef ARCANE_UTILS_INTERNAL_DEPENDENCYINJECTION_H
13#define ARCANE_UTILS_INTERNAL_DEPENDENCYINJECTION_H
21#include "arcane/utils/Ref.h"
22#include "arcane/utils/ExternalRef.h"
23#include "arcane/utils/GenericRegisterer.h"
28#include "arcane/utils/NotImplementedException.h"
43namespace Arcane::DependencyInjection
48namespace Arcane::DependencyInjection::impl
52class IInstanceFactory;
53template <
typename InterfaceType>
55class ConcreteFactoryTypeInfo;
63namespace Arcane::DependencyInjection
69class ARCANE_UTILS_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 ARCANE_UTILS_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;
149class ARCANE_UTILS_EXPORT ConcreteFactoryTypeInfo
153 ConcreteFactoryTypeInfo(TypeInfo&& a, TypeInfo&& b, TypeInfo&& c)
154 : m_interface_info(a)
156 , m_constructor_info(c)
161 template <
typename InterfaceType,
typename ConcreteType,
typename ConstructorType>
162 static ConcreteFactoryTypeInfo create()
164 return ConcreteFactoryTypeInfo(TypeInfo::create<InterfaceType>(),
165 TypeInfo::create<ConcreteType>(),
166 TypeInfo::create<ConstructorType>());
168 const TypeInfo& interfaceTypeInfo()
const {
return m_interface_info; }
169 const TypeInfo& concreteTypeInfo()
const {
return m_concrete_info; }
170 const TypeInfo& constructorTypeInfo()
const {
return m_constructor_info; }
174 TypeInfo m_interface_info;
175 TypeInfo m_concrete_info;
176 TypeInfo m_constructor_info;
185template <
typename InterfaceType>
186class IInjectedRefInstanceT
187:
public IInjectedInstance
191 virtual Ref<InterfaceType> instance() = 0;
202template <
typename InterfaceType>
203class InjectedRefInstance
204:
public IInjectedRefInstanceT<InterfaceType>
208 using InstanceType = Ref<InterfaceType>;
212 InjectedRefInstance(InstanceType t_instance,
const String& t_name)
213 : m_instance(t_instance)
219 Ref<InterfaceType> instance()
override {
return m_instance; }
220 bool hasName(
const String& str)
const override {
return m_name == str; }
221 bool hasTypeInfo(
const std::type_info& tinfo)
const override {
return typeid(InstanceType) == tinfo; }
225 InstanceType m_instance;
235template <
typename Type>
236class IInjectedValueInstance
237:
public IInjectedInstance
241 virtual Type instance()
const = 0;
250template <
typename Type>
251class InjectedValueInstance
252:
public IInjectedValueInstance<Type>
256 using InstanceType =
Type;
260 InjectedValueInstance(
Type t_instance,
const String& t_name)
261 : m_instance(t_instance)
267 Type instance()
const override {
return m_instance; }
268 bool hasName(
const String& str)
const override {
return m_name == str; }
269 bool hasTypeInfo(
const std::type_info& tinfo)
const override {
return typeid(InstanceType) == tinfo; }
285class ARCANE_UTILS_EXPORT InjectedInstanceRef
287 typedef Ref<IInjectedInstance> RefType;
291 explicit InjectedInstanceRef(
const RefType& r)
297 InjectedInstanceRef() =
default;
301 static InjectedInstanceRef
createRef(IInjectedInstance* p)
303 return InjectedInstanceRef(RefType::create(p));
305 static InjectedInstanceRef createRefNoDestroy(IInjectedInstance* p)
307 return InjectedInstanceRef(RefType::_createNoDestroy(p));
309 static InjectedInstanceRef createWithHandle(IInjectedInstance* p, Internal::ExternalRef handle)
311 return InjectedInstanceRef(RefType::createWithHandle(p, handle));
316 IInjectedInstance* get()
const {
return m_instance.get(); }
317 void reset() { m_instance.reset(); }
330class ARCANE_UTILS_EXPORT IInstanceFactory
336 virtual ~IInstanceFactory() =
default;
340 virtual InjectedInstanceRef createGenericReference(Injector& injector,
const String& name) = 0;
341 virtual const FactoryInfoImpl* factoryInfoImpl()
const = 0;
342 virtual ConcreteFactoryTypeInfo concreteFactoryInfo()
const = 0;
343 virtual Int32 nbConstructorArg()
const = 0;
352class ARCANE_UTILS_EXPORT FactoryInfo
354 friend class Arcane::DependencyInjection::Injector;
358 explicit FactoryInfo(
const ProviderProperty& property);
362 static FactoryInfo create(
const ProviderProperty& property,
const char* file_name,
int line_number)
364 ARCANE_UNUSED(file_name);
365 ARCANE_UNUSED(line_number);
366 return FactoryInfo(property);
368 void addFactory(Ref<IInstanceFactory> f);
369 bool hasName(
const String& str)
const;
370 const FactoryInfoImpl* _impl()
const {
return m_p.get(); }
374 std::shared_ptr<FactoryInfoImpl> m_p;
385class ARCANE_UTILS_EXPORT AbstractInstanceFactory
386:
public ReferenceCounterImpl
387,
public IInstanceFactory
395template <
typename InterfaceType>
397:
public AbstractInstanceFactory
405 InstanceFactory(
const FactoryInfoImpl* si, IConcreteFactory<InterfaceType>* sub_factory)
406 : m_factory_info_impl(si)
407 , m_sub_factory(sub_factory)
411 ~InstanceFactory()
override
413 delete m_sub_factory;
416 InjectedInstanceRef createGenericReference(Injector& injector,
const String& name)
override
418 return _create(_createReference(injector), name);
421 Ref<InterfaceType> createReference(Injector& injector)
423 return _createReference(injector);
426 const FactoryInfoImpl* factoryInfoImpl()
const override
428 return m_factory_info_impl;
431 ConcreteFactoryTypeInfo concreteFactoryInfo()
const override
433 return m_sub_factory->concreteFactoryInfo();
436 Int32 nbConstructorArg()
const override
438 return m_sub_factory->nbConstructorArg();
443 const FactoryInfoImpl* m_factory_info_impl =
nullptr;
444 IConcreteFactory<InterfaceType>* m_sub_factory =
nullptr;
448 Ref<InterfaceType> _createReference(Injector& injector)
450 return m_sub_factory->createReference(injector);
453 InjectedInstanceRef _create(Ref<InterfaceType> it,
const String& name)
455 IInjectedInstance* x = (!it) ?
nullptr : new InjectedRefInstance<InterfaceType>(it, name);
456 return InjectedInstanceRef::createRef(x);
463class ARCANE_UTILS_EXPORT IConcreteFactoryBase
467 virtual ~IConcreteFactoryBase() =
default;
471 virtual ConcreteFactoryTypeInfo concreteFactoryInfo()
const = 0;
472 virtual Int32 nbConstructorArg()
const = 0;
482template <
typename InterfaceType>
484:
public IConcreteFactoryBase
488 virtual ~IConcreteFactory() =
default;
493 virtual Ref<InterfaceType> createReference(Injector&) = 0;
499class ARCANE_UTILS_EXPORT GlobalRegisterer
500:
public GenericRegisterer<GlobalRegisterer>
502 using BaseClass = GenericRegisterer<GlobalRegisterer>;
503 static BaseClass::Info m_global_registerer_info;
507 static GenericRegisterer<GlobalRegisterer>::Info& registererInfo()
509 return m_global_registerer_info;
514 typedef FactoryInfo (*FactoryCreateFunc)(
const ProviderProperty& property);
523 GlobalRegisterer(FactoryCreateFunc func,
const ProviderProperty& property)
noexcept;
527 FactoryCreateFunc infoCreatorWithPropertyFunction() {
return m_factory_create_func; }
530 const char* name() {
return m_name; }
532 const ProviderProperty& property()
const {
return m_factory_property; }
536 FactoryCreateFunc m_factory_create_func =
nullptr;
537 const char* m_name =
nullptr;
538 ProviderProperty m_factory_property;
548namespace Arcane::DependencyInjection
556class ARCANE_UTILS_EXPORT Injector
559 using FactoryFilterFunc = bool (*)(impl::IInstanceFactory*);
561 template <
class Type>
566 static IInjectedInstance* bind(
const Type& t,
const String& name)
568 return new impl::InjectedValueInstance<Type>(t, name);
570 static Type get(Injector& i,
const String& name)
572 return i._getValue<
Type>(name);
577 template <
class Po
interType>
578 class InjectorHelper<Ref<PointerType>>
582 using ThatType = Ref<PointerType>;
586 static IInjectedInstance* bind(
const ThatType& t,
const String& name)
588 return new impl::InjectedRefInstance<PointerType>(t, name);
590 static ThatType get(Injector& i,
const String& name)
592 return i._getRef<PointerType>(name);
598 class IFactoryVisitorFunctor
602 virtual ~IFactoryVisitorFunctor() =
default;
603 virtual bool execute(impl::IInstanceFactory* f) = 0;
606 template <
typename Lambda>
class FactoryVisitorFunctor
607 :
public IFactoryVisitorFunctor
611 FactoryVisitorFunctor(Lambda& lambda)
617 virtual bool execute(impl::IInstanceFactory* f) {
return m_lambda(f); }
627 class IInstanceVisitorFunctor
631 virtual ~IInstanceVisitorFunctor() =
default;
632 virtual bool execute(IInjectedInstance* v) = 0;
635 template <
typename Lambda>
class InstanceVisitorFunctor
636 :
public IInstanceVisitorFunctor
640 InstanceVisitorFunctor(Lambda& lambda)
646 virtual bool execute(IInjectedInstance* v) {
return m_lambda(v); }
656 Injector(
const Injector&) =
delete;
657 Injector& operator=(
const Injector&) =
delete;
662 template <
typename Type>
void
663 bind(
Type iref,
const String& name = String())
665 _add(InjectorHelper<Type>::bind(iref, name));
668 template <
typename Type>
Type
669 get(
const String& name = String())
671 return InjectorHelper<Type>::get(*
this, name);
687 template <
typename InterfaceType> Ref<InterfaceType>
688 createInstance(
const String& implementation_name,
bool allow_null =
false)
690 using FactoryType = impl::InstanceFactory<InterfaceType>;
691 Ref<InterfaceType> instance;
692 auto f = [&](impl::IInstanceFactory* v) ->
bool {
693 auto* t =
dynamic_cast<FactoryType*
>(v);
696 Ref<InterfaceType> x = t->createReference(*
this);
704 FactoryVisitorFunctor ff(f);
705 _iterateFactories(implementation_name, &ff);
706 if (instance.get() || allow_null)
712 auto filter_func = [](impl::IInstanceFactory* v) ->
bool {
713 return dynamic_cast<FactoryType*
>(v) !=
nullptr;
715 _printValidImplementationAndThrow(A_FUNCINFO, implementation_name, filter_func);
718 String printFactories()
const;
720 void fillWithGlobalFactories();
728 void _add(IInjectedInstance* instance);
731 void _iterateInstances(
const std::type_info& t_info,
const String& instance_name,
732 IInstanceVisitorFunctor* lambda);
734 IInjectedInstance* _value(Integer i)
const;
744 void _iterateFactories(
const String& factory_name, IFactoryVisitorFunctor* functor)
const;
746 impl::IInstanceFactory* _factory(Integer i)
const;
749 template <
typename InterfaceType> Ref<InterfaceType>
750 _getRef(
const String& instance_name)
752 using InjectedType = impl::IInjectedRefInstanceT<InterfaceType>;
753 InjectedType* t =
nullptr;
754 auto f = [&](IInjectedInstance* v) ->
bool {
755 t =
dynamic_cast<InjectedType*
>(v);
758 InstanceVisitorFunctor ff(f);
759 _iterateInstances(
typeid(Ref<InterfaceType>), instance_name, &ff);
761 return t->instance();
763 ARCANE_THROW(NotImplementedException,
"Create Ref<InterfaceType> from factory");
766 template <
typename Type>
Type
767 _getValue(
const String& instance_name)
769 using InjectedType = impl::IInjectedValueInstance<Type>;
770 InjectedType* t =
nullptr;
771 auto f = [&](IInjectedInstance* v) ->
bool {
772 t =
dynamic_cast<InjectedType*
>(v);
775 InstanceVisitorFunctor ff(f);
776 _iterateInstances(
typeid(
Type), instance_name, &ff);
778 return t->instance();
779 _doError(A_FUNCINFO,
"Can not find value for type");
781 [[noreturn]]
void _printValidImplementationAndThrow(
const TraceInfo& ti,
782 const String& implementation_name,
783 FactoryFilterFunc filter_func);
784 [[noreturn]]
void _doError(
const TraceInfo& ti,
const String& message);
792namespace Arcane::DependencyInjection::impl
798class ARCANE_UTILS_EXPORT ConstructorRegistererBase
802 [[noreturn]]
void _doError1(
const String& message,
int nb_value);
811template <
typename... Args>
812class ConstructorRegisterer
813:
public ConstructorRegistererBase
817 using ArgsType = std::tuple<Args...>;
819 ConstructorRegisterer() {}
822 template <std::
size_t I>
823 static auto _get(Injector& i) -> std::tuple_element_t<I, ArgsType>
825 using SelectedType = std::tuple_element_t<I, ArgsType>;
827 return i.get<SelectedType>();
830 ArgsType createTuple(Injector& i)
833 constexpr int tuple_size = std::tuple_size<ArgsType>();
834 static_assert(tuple_size < 3,
"Too many arguments for createTuple (max=2)");
835 if constexpr (tuple_size == 0) {
838 else if constexpr (tuple_size == 1) {
839 return ArgsType(_get<0>(i));
841 else if constexpr (tuple_size == 2) {
842 return ArgsType(_get<0>(i), _get<1>(i));
845 _doError1(
"Too many arguments for createTuple n={0} max=2", tuple_size);
856template <
typename InterfaceType,
typename ConcreteType,
typename ConstructorType>
860 using Args =
typename ConstructorType::ArgsType;
864 Ref<InterfaceType> createReference(Injector& injector)
override
867 ConcreteType* st = _create(ct.createTuple(injector));
868 return makeRef<InterfaceType>(st);
870 ConcreteFactoryTypeInfo concreteFactoryInfo()
const override
872 return ConcreteFactoryTypeInfo::create<InterfaceType, ConcreteType, ConstructorType>();
874 Int32 nbConstructorArg()
const override
876 return std::tuple_size<Args>();
886 ConcreteType* _create(
const Args&& tuple_args)
888 ConcreteType* st = std::apply([](
auto&&... args) -> ConcreteType* {
return new ConcreteType(args...); }, tuple_args);
900template <
typename... Interfaces>
901class InterfaceListRegisterer
911 template <
typename ConcreteType,
typename ConstructorType>
void
912 registerFactory(FactoryInfo& si)
914 _registerFactory<ConcreteType, ConstructorType, Interfaces...>(si);
919 template <
typename ConcreteType,
typename ConstructorType,
920 typename InterfaceType,
typename... OtherInterfaces>
922 _registerFactory(FactoryInfo& fi)
924 auto* factory =
new ConcreteFactory<InterfaceType, ConcreteType, ConstructorType>();
925 fi.addFactory(createRef<InstanceFactory<InterfaceType>>(fi._impl(), factory));
927 if constexpr (
sizeof...(OtherInterfaces) > 0)
928 _registerFactory<ConcreteType, ConstructorType, OtherInterfaces...>(fi);
940template <
typename ConcreteType,
typename InterfaceList>
941class InjectionRegisterer
946 template <
typename... Constructors>
void
947 registerProviderInfo(FactoryInfo& si,
const Constructors&... args)
949 _create(si, args...);
955 InterfaceList m_interface_list;
960 template <
typename ConstructorType>
void
961 _create(FactoryInfo& si,
const ConstructorType&)
963 m_interface_list.template registerFactory<ConcreteType, ConstructorType>(si);
967 template <
typename C1,
typename C2,
typename... OtherConstructors>
968 void _create(FactoryInfo& si,
const C1& c1,
const C2& c2,
const OtherConstructors&... args)
972 _create<C2, OtherConstructors...>(si, c2, args...);
984#define ARCANE_DI_CONSTRUCTOR(...) \
985 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<__VA_ARGS__>()
987#define ARCANE_DI_EMPTY_CONSTRUCTOR(...) \
988 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<>()
992#define ARCANE_DI_INTERFACES(...) \
993 ::Arcane::DependencyInjection::impl::InterfaceListRegisterer<__VA_ARGS__>
995#define ARCANE_DI_REGISTER_PROVIDER(t_class, t_provider_property, t_interfaces, ...) \
998 Arcane::DependencyInjection::impl::FactoryInfo \
999 ARCANE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class)(const Arcane::DependencyInjection::ProviderProperty& property) \
1001 auto si = Arcane::DependencyInjection::impl::FactoryInfo::create(property, __FILE__, __LINE__); \
1002 Arcane::DependencyInjection::impl::InjectionRegisterer<t_class, t_interfaces> injection_registerer; \
1003 injection_registerer.registerProviderInfo(si, __VA_ARGS__); \
1007 Arcane::DependencyInjection::impl::GlobalRegisterer ARCANE_EXPORT ARCANE_JOIN_WITH_LINE(globalServiceRegisterer##aclass)(&ARCANE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class), t_provider_property)
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCCORE_DECLARE_REFERENCE_COUNTED_INCLASS_METHODS()
Macro pour déclarer les méthodes virtuelles gérant les compteurs de référence.
#define ARCCORE_DECLARE_REFERENCE_COUNTED_CLASS(class_name)
Macro pour déclarer qu'une classe utilise un compteur de référence.
#define ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS()
Macro pour définir les méthodes gérant les compteurs de référence.
Chaîne de caractères unicode.
Ref< TrueType > createRef(Args &&... args)
Créé une instance de type TrueType avec les arguments Args et retourne une référence dessus.
Int32 Integer
Type représentant un entier.