12#ifndef ARCANE_UTILS_DEPENDENCYINJECTION_H
13#define ARCANE_UTILS_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
51class IInstanceFactory;
52template <
typename InterfaceType>
54class ConcreteFactoryTypeInfo;
62namespace Arcane::DependencyInjection
68class ARCANE_UTILS_EXPORT IInjectedInstance
71 virtual ~IInjectedInstance() =
default;
72 virtual bool hasName(
const String& str)
const = 0;
73 virtual bool hasTypeInfo(
const std::type_info& tinfo)
const = 0;
84class ARCANE_UTILS_EXPORT ProviderProperty
87 ProviderProperty(
const char* name)
92 const char* name()
const {
return m_name; }
106namespace Arcane::DependencyInjection::impl
115 TypeInfo(
const TraceInfo& trace_info,
const std::type_info& type_info)
116 : m_trace_info(trace_info)
117 , m_type_info(type_info)
121 template <
typename Type>
static TypeInfo create()
123 return TypeInfo(A_FUNCINFO,
typeid(Type));
125 const TraceInfo& traceInfo()
const {
return m_trace_info; }
126 const std::type_info& stdTypeInfo()
const {
return m_type_info; }
129 TraceInfo m_trace_info;
130 const std::type_info& m_type_info;
142class ARCANE_UTILS_EXPORT ConcreteFactoryTypeInfo
145 ConcreteFactoryTypeInfo(TypeInfo&& a, TypeInfo&& b, TypeInfo&& c)
146 : m_interface_info(a)
148 , m_constructor_info(c)
152 template <
typename InterfaceType,
typename ConcreteType,
typename ConstructorType>
153 static ConcreteFactoryTypeInfo create()
155 return ConcreteFactoryTypeInfo(TypeInfo::create<InterfaceType>(),
156 TypeInfo::create<ConcreteType>(),
157 TypeInfo::create<ConstructorType>());
159 const TypeInfo& interfaceTypeInfo()
const {
return m_interface_info; }
160 const TypeInfo& concreteTypeInfo()
const {
return m_concrete_info; }
161 const TypeInfo& constructorTypeInfo()
const {
return m_constructor_info; }
164 TypeInfo m_interface_info;
165 TypeInfo m_concrete_info;
166 TypeInfo m_constructor_info;
175template <
typename InterfaceType>
176class IInjectedRefInstanceT
177:
public IInjectedInstance
180 virtual Ref<InterfaceType> instance() = 0;
191template <
typename InterfaceType>
192class InjectedRefInstance
193:
public IInjectedRefInstanceT<InterfaceType>
196 using InstanceType = Ref<InterfaceType>;
199 InjectedRefInstance(InstanceType t_instance,
const String& t_name)
200 : m_instance(t_instance)
205 Ref<InterfaceType> instance()
override {
return m_instance; }
206 bool hasName(
const String& str)
const override {
return m_name == str; }
207 bool hasTypeInfo(
const std::type_info& tinfo)
const override {
return typeid(InstanceType) == tinfo; }
210 InstanceType m_instance;
220template <
typename Type>
221class IInjectedValueInstance
222:
public IInjectedInstance
225 virtual Type instance()
const = 0;
236template <
typename Type>
237class InjectedValueInstance
238:
public IInjectedValueInstance<Type>
241 using InstanceType = Type;
244 InjectedValueInstance(Type t_instance,
const String& t_name)
245 : m_instance(t_instance)
250 Type instance()
const override {
return m_instance; }
251 bool hasName(
const String& str)
const override {
return m_name == str; }
252 bool hasTypeInfo(
const std::type_info& tinfo)
const override {
return typeid(InstanceType) == tinfo; }
267class ARCANE_UTILS_EXPORT InjectedInstanceRef
269 typedef Ref<IInjectedInstance> RefType;
272 InjectedInstanceRef(
const RefType& r)
277 InjectedInstanceRef() =
default;
280 static InjectedInstanceRef createRef(IInjectedInstance* p)
282 return InjectedInstanceRef(RefType::create(p));
284 static InjectedInstanceRef createRefNoDestroy(IInjectedInstance* p)
286 return InjectedInstanceRef(RefType::_createNoDestroy(p));
288 static InjectedInstanceRef createWithHandle(IInjectedInstance* p, Internal::ExternalRef handle)
290 return InjectedInstanceRef(RefType::createWithHandle(p, handle));
294 IInjectedInstance* get()
const {
return m_instance.get(); }
295 void reset() { m_instance.reset(); }
307class ARCANE_UTILS_EXPORT IInstanceFactory
312 virtual ~IInstanceFactory() =
default;
315 virtual InjectedInstanceRef createGenericReference(Injector& injector,
const String& name) = 0;
317 virtual const FactoryInfo* factoryInfo()
const = 0;
319 virtual ConcreteFactoryTypeInfo concreteFactoryInfo()
const = 0;
321 virtual Int32 nbConstructorArg()
const = 0;
332class ARCANE_UTILS_EXPORT AbstractInstanceFactory
333:
public ReferenceCounterImpl
334,
public IInstanceFactory
342template <
typename InterfaceType>
344:
public AbstractInstanceFactory
347 InstanceFactory(FactoryInfo* si, IConcreteFactory<InterfaceType>* sub_factory)
349 , m_sub_factory(sub_factory)
353 ~InstanceFactory()
override
355 delete m_sub_factory;
358 InjectedInstanceRef createGenericReference(Injector& injector,
const String& name)
override
360 return _create(_createReference(injector), name);
363 Ref<InterfaceType> createReference(Injector& injector)
365 return _createReference(injector);
368 const FactoryInfo* factoryInfo()
const override
370 return m_factory_info;
373 ConcreteFactoryTypeInfo concreteFactoryInfo()
const override
375 return m_sub_factory->concreteFactoryInfo();
378 Int32 nbConstructorArg()
const override
380 return m_sub_factory->nbConstructorArg();
384 FactoryInfo* m_factory_info;
385 IConcreteFactory<InterfaceType>* m_sub_factory;
388 Ref<InterfaceType> _createReference(Injector& injector)
390 return m_sub_factory->createReference(injector);
393 InjectedInstanceRef _create(Ref<InterfaceType> it,
const String& name)
395 IInjectedInstance* x = (!it) ?
nullptr : new InjectedRefInstance<InterfaceType>(it, name);
396 return InjectedInstanceRef::createRef(x);
403class ARCANE_UTILS_EXPORT IConcreteFactoryBase
406 virtual ~IConcreteFactoryBase() =
default;
409 virtual ConcreteFactoryTypeInfo concreteFactoryInfo()
const = 0;
410 virtual Int32 nbConstructorArg()
const = 0;
420template <
typename InterfaceType>
421class IConcreteFactory
422:
public IConcreteFactoryBase
425 virtual ~IConcreteFactory() =
default;
429 virtual Ref<InterfaceType> createReference(Injector&) = 0;
438class ARCANE_UTILS_EXPORT FactoryInfo
440 friend class Arcane::DependencyInjection::Injector;
444 FactoryInfo(
const FactoryInfo&) =
delete;
445 FactoryInfo& operator=(
const FactoryInfo&) =
delete;
449 FactoryInfo(
const ProviderProperty& property);
452 static FactoryInfo* create(
const ProviderProperty& property,
const char* file_name,
int line_number)
454 ARCANE_UNUSED(file_name);
455 ARCANE_UNUSED(line_number);
456 return new FactoryInfo(property);
458 void addFactory(Ref<IInstanceFactory> f);
459 bool hasName(
const String& str)
const;
468class ARCANE_UTILS_EXPORT GlobalRegisterer
469:
public GenericRegisterer<GlobalRegisterer>
471 using BaseClass = GenericRegisterer<GlobalRegisterer>;
472 static BaseClass::Info m_global_registerer_info;
476 static GenericRegisterer<GlobalRegisterer>::Info& registererInfo()
478 return m_global_registerer_info;
483 typedef FactoryInfo* (*FactoryCreateFunc)(
const ProviderProperty& property);
491 GlobalRegisterer(FactoryCreateFunc func,
const ProviderProperty& property)
noexcept;
495 FactoryCreateFunc infoCreatorWithPropertyFunction() {
return m_factory_create_func; }
498 const char* name() {
return m_name; }
500 const ProviderProperty& property()
const {
return m_factory_property; }
504 FactoryCreateFunc m_factory_create_func =
nullptr;
505 const char* m_name =
nullptr;
506 ProviderProperty m_factory_property;
516namespace Arcane::DependencyInjection
524class ARCANE_UTILS_EXPORT Injector
528 template <
class Type>
532 static IInjectedInstance* bind(
const Type& t,
const String& name)
534 return new impl::InjectedValueInstance<Type>(t, name);
536 static Type get(Injector& i,
const String& name)
538 return i._getValue<Type>(name);
543 template <
class Po
interType>
544 class InjectorHelper<Ref<PointerType>>
547 using ThatType = Ref<PointerType>;
550 static IInjectedInstance* bind(
const ThatType& t,
const String& name)
552 return new impl::InjectedRefInstance<PointerType>(t, name);
554 static ThatType get(Injector& i,
const String& name)
556 return i._getRef<PointerType>(name);
562 class IFactoryVisitorFunctor
565 virtual ~IFactoryVisitorFunctor() =
default;
566 virtual bool execute(impl::IInstanceFactory* f) = 0;
569 template <
typename Lambda>
class FactoryVisitorFunctor
570 :
public IFactoryVisitorFunctor
573 FactoryVisitorFunctor(Lambda& lambda)
578 virtual bool execute(impl::IInstanceFactory* f) {
return m_lambda(f); }
587 class IInstanceVisitorFunctor
590 virtual ~IInstanceVisitorFunctor() =
default;
591 virtual bool execute(IInjectedInstance* v) = 0;
594 template <
typename Lambda>
class InstanceVisitorFunctor
595 :
public IInstanceVisitorFunctor
598 InstanceVisitorFunctor(Lambda& lambda)
603 virtual bool execute(IInjectedInstance* v) {
return m_lambda(v); }
611 Injector(
const Injector&) =
delete;
612 Injector& operator=(
const Injector&) =
delete;
616 template <
typename Type>
void
617 bind(Type iref,
const String& name = String())
619 _add(InjectorHelper<Type>::bind(iref, name));
622 template <
typename Type> Type
623 get(
const String& name = String())
625 return InjectorHelper<Type>::get(*
this, name);
628 template <
typename InterfaceType> Ref<InterfaceType>
629 createInstance(
const String& service_name = String())
631 using FactoryType = impl::InstanceFactory<InterfaceType>;
632 Ref<InterfaceType> instance;
633 auto f = [&](impl::IInstanceFactory* v) ->
bool {
634 auto* t =
dynamic_cast<FactoryType*
>(v);
637 Ref<InterfaceType> x = t->createReference(*
this);
645 FactoryVisitorFunctor ff(f);
646 _iterateFactories(service_name, &ff);
650 _doError(A_FUNCINFO,
"Can not create instance");
653 String printFactories()
const;
655 void fillWithGlobalFactories();
661 void _add(IInjectedInstance* instance);
664 void _iterateInstances(
const std::type_info& t_info,
const String& instance_name,
665 IInstanceVisitorFunctor* lambda);
667 IInjectedInstance* _value(Integer i)
const;
677 void _iterateFactories(
const String& factory_name, IFactoryVisitorFunctor* functor)
const;
679 impl::IInstanceFactory* _factory(Integer i)
const;
682 template <
typename InterfaceType> Ref<InterfaceType>
683 _getRef(
const String& instance_name)
685 using InjectedType = impl::IInjectedRefInstanceT<InterfaceType>;
686 InjectedType* t =
nullptr;
687 auto f = [&](IInjectedInstance* v) ->
bool {
688 t =
dynamic_cast<InjectedType*
>(v);
691 InstanceVisitorFunctor ff(f);
692 _iterateInstances(
typeid(Ref<InterfaceType>), instance_name, &ff);
694 return t->instance();
696 ARCANE_THROW(NotImplementedException,
"Create Ref<InterfaceType> from factory");
699 template <
typename Type> Type
700 _getValue(
const String& instance_name)
702 using InjectedType = impl::IInjectedValueInstance<Type>;
703 InjectedType* t =
nullptr;
704 auto f = [&](IInjectedInstance* v) ->
bool {
705 t =
dynamic_cast<InjectedType*
>(v);
708 InstanceVisitorFunctor ff(f);
709 _iterateInstances(
typeid(Type), instance_name, &ff);
711 return t->instance();
712 _doError(A_FUNCINFO,
"Can not find value for type");
714 [[noreturn]]
void _doError(
const TraceInfo& ti,
const String& message);
722namespace Arcane::DependencyInjection::impl
728class ARCANE_UTILS_EXPORT ConstructorRegistererBase
731 [[noreturn]]
void _doError1(
const String& message,
int nb_value);
740template <
typename... Args>
741class ConstructorRegisterer
742:
public ConstructorRegistererBase
745 using ArgsType = std::tuple<Args...>;
747 ConstructorRegisterer() {}
750 template <std::
size_t I>
751 static auto _get(Injector& i) -> std::tuple_element_t<I, ArgsType>
753 using SelectedType = std::tuple_element_t<I, ArgsType>;
755 return i.get<SelectedType>();
758 ArgsType createTuple(Injector& i)
761 constexpr int tuple_size = std::tuple_size<ArgsType>();
762 static_assert(tuple_size < 3,
"Too many arguments for createTuple (max=2)");
763 if constexpr (tuple_size == 0) {
766 else if constexpr (tuple_size == 1) {
767 return ArgsType(_get<0>(i));
769 else if constexpr (tuple_size == 2) {
770 return ArgsType(_get<0>(i), _get<1>(i));
773 _doError1(
"Too many arguments for createTuple n={0} max=2", tuple_size);
784template <
typename InterfaceType,
typename ConcreteType,
typename ConstructorType>
786:
public IConcreteFactory<InterfaceType>
788 using Args =
typename ConstructorType::ArgsType;
791 Ref<InterfaceType> createReference(Injector& injector)
override
794 ConcreteType* st = _create(ct.createTuple(injector));
795 return makeRef<InterfaceType>(st);
797 ConcreteFactoryTypeInfo concreteFactoryInfo()
const override
799 return ConcreteFactoryTypeInfo::create<InterfaceType, ConcreteType, ConstructorType>();
801 Int32 nbConstructorArg()
const override
803 return std::tuple_size<Args>();
812 ConcreteType* _create(
const Args&& tuple_args)
814 ConcreteType* st = std::apply([](
auto&&... args) -> ConcreteType* {
return new ConcreteType(args...); }, tuple_args);
826template <
typename... Interfaces>
827class InterfaceListRegisterer
836 template <
typename ConcreteType,
typename ConstructorType>
void
837 registerFactory(FactoryInfo* si)
839 _registerFactory<ConcreteType, ConstructorType, Interfaces...>(si);
843 template <
typename ConcreteType,
typename ConstructorType,
844 typename InterfaceType,
typename... OtherInterfaces>
846 _registerFactory(FactoryInfo* fi)
848 auto* factory =
new ConcreteFactory<InterfaceType, ConcreteType, ConstructorType>();
849 fi->addFactory(createRef<InstanceFactory<InterfaceType>>(fi, factory));
851 if constexpr (
sizeof...(OtherInterfaces) > 0)
852 _registerFactory<ConcreteType, ConstructorType, OtherInterfaces...>(fi);
864template <
typename ConcreteType,
typename InterfaceList>
865class InjectionRegisterer
869 template <
typename... Constructors>
void
870 registerProviderInfo(FactoryInfo* si,
const Constructors&... args)
872 _create(si, args...);
877 InterfaceList m_interface_list;
881 template <
typename ConstructorType>
void
882 _create(FactoryInfo* si,
const ConstructorType&)
884 m_interface_list.template registerFactory<ConcreteType, ConstructorType>(si);
888 template <
typename C1,
typename C2,
typename... OtherConstructors>
889 void _create(FactoryInfo* si,
const C1& c1,
const C2& c2,
const OtherConstructors&... args)
893 _create<C2, OtherConstructors...>(si, c2, args...);
905#define ARCANE_DI_CONSTRUCTOR(...) \
906 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<__VA_ARGS__>()
908#define ARCANE_DI_EMPTY_CONSTRUCTOR(...) \
909 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<>()
913#define ARCANE_DI_INTERFACES(...) \
914 ::Arcane::DependencyInjection::impl::InterfaceListRegisterer<__VA_ARGS__>
916#define ARCANE_DI_REGISTER_PROVIDER(t_class, t_provider_property, t_interfaces, ...) \
919 Arcane::DependencyInjection::impl::FactoryInfo* \
920 ARCANE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class)(const Arcane::DependencyInjection::ProviderProperty& property) \
922 auto* si = Arcane::DependencyInjection::impl::FactoryInfo::create(property, __FILE__, __LINE__); \
923 Arcane::DependencyInjection::impl::InjectionRegisterer<t_class, t_interfaces> injection_registerer; \
924 injection_registerer.registerProviderInfo(si, __VA_ARGS__); \
928 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.
Int32 Integer
Type représentant un entier.