12#ifndef ARCCORE_BASE_INTERNAL_DEPENDENCYINJECTION_H
13#define ARCCORE_BASE_INTERNAL_DEPENDENCYINJECTION_H
21#include "arccore/base/ExternalRef.h"
22#include "arccore/base/GenericRegisterer.h"
26#include "arccore/base/NotImplementedException.h"
41namespace Arcane::DependencyInjection
46namespace Arcane::DependencyInjection::impl
50class IInstanceFactory;
51template <
typename InterfaceType>
53class ConcreteFactoryTypeInfo;
61namespace Arcane::DependencyInjection
67class ARCCORE_BASE_EXPORT IInjectedInstance
70 virtual ~IInjectedInstance() =
default;
71 virtual bool hasName(
const String& str)
const = 0;
72 virtual bool hasTypeInfo(
const std::type_info& tinfo)
const = 0;
83class ARCCORE_BASE_EXPORT ProviderProperty
87 ProviderProperty(
const char* name)
93 const char* name()
const {
return m_name; }
108namespace Arcane::DependencyInjection::impl
118 TypeInfo(
const TraceInfo& trace_info,
const std::type_info& type_info)
119 : m_trace_info(trace_info)
120 , m_type_info(type_info)
125 template <
typename Type>
static TypeInfo create()
127 return TypeInfo(A_FUNCINFO,
typeid(
Type));
129 const TraceInfo& traceInfo()
const {
return m_trace_info; }
130 const std::type_info& stdTypeInfo()
const {
return m_type_info; }
134 TraceInfo m_trace_info;
135 const std::type_info& m_type_info;
147class ARCCORE_BASE_EXPORT ConcreteFactoryTypeInfo
151 ConcreteFactoryTypeInfo(TypeInfo&& a, TypeInfo&& b, TypeInfo&& c)
152 : m_interface_info(a)
154 , m_constructor_info(c)
159 template <
typename InterfaceType,
typename ConcreteType,
typename ConstructorType>
160 static ConcreteFactoryTypeInfo create()
162 return ConcreteFactoryTypeInfo(TypeInfo::create<InterfaceType>(),
163 TypeInfo::create<ConcreteType>(),
164 TypeInfo::create<ConstructorType>());
166 const TypeInfo& interfaceTypeInfo()
const {
return m_interface_info; }
167 const TypeInfo& concreteTypeInfo()
const {
return m_concrete_info; }
168 const TypeInfo& constructorTypeInfo()
const {
return m_constructor_info; }
172 TypeInfo m_interface_info;
173 TypeInfo m_concrete_info;
174 TypeInfo m_constructor_info;
183template <
typename InterfaceType>
184class IInjectedRefInstanceT
185:
public IInjectedInstance
189 virtual Ref<InterfaceType> instance() = 0;
200template <
typename InterfaceType>
201class InjectedRefInstance
202:
public IInjectedRefInstanceT<InterfaceType>
206 using InstanceType = Ref<InterfaceType>;
210 InjectedRefInstance(InstanceType t_instance,
const String& t_name)
211 : m_instance(t_instance)
217 Ref<InterfaceType> instance()
override {
return m_instance; }
218 bool hasName(
const String& str)
const override {
return m_name == str; }
219 bool hasTypeInfo(
const std::type_info& tinfo)
const override {
return typeid(InstanceType) == tinfo; }
223 InstanceType m_instance;
233template <
typename Type>
234class IInjectedValueInstance
235:
public IInjectedInstance
239 virtual Type instance()
const = 0;
248template <
typename Type>
249class InjectedValueInstance
250:
public IInjectedValueInstance<Type>
254 using InstanceType =
Type;
258 InjectedValueInstance(
Type t_instance,
const String& t_name)
259 : m_instance(t_instance)
265 Type instance()
const override {
return m_instance; }
266 bool hasName(
const String& str)
const override {
return m_name == str; }
267 bool hasTypeInfo(
const std::type_info& tinfo)
const override {
return typeid(InstanceType) == tinfo; }
283class ARCCORE_BASE_EXPORT InjectedInstanceRef
285 typedef Ref<IInjectedInstance> RefType;
289 explicit InjectedInstanceRef(
const RefType& r)
295 InjectedInstanceRef() =
default;
299 static InjectedInstanceRef
createRef(IInjectedInstance* p)
301 return InjectedInstanceRef(RefType::create(p));
303 static InjectedInstanceRef createRefNoDestroy(IInjectedInstance* p)
305 return InjectedInstanceRef(RefType::_createNoDestroy(p));
307 static InjectedInstanceRef createWithHandle(IInjectedInstance* p, Internal::ExternalRef handle)
309 return InjectedInstanceRef(RefType::createWithHandle(p, handle));
314 IInjectedInstance* get()
const {
return m_instance.get(); }
315 void reset() { m_instance.reset(); }
328class ARCCORE_BASE_EXPORT IInstanceFactory
334 virtual ~IInstanceFactory() =
default;
338 virtual InjectedInstanceRef createGenericReference(Injector& injector,
const String& name) = 0;
339 virtual const FactoryInfoImpl* factoryInfoImpl()
const = 0;
340 virtual ConcreteFactoryTypeInfo concreteFactoryInfo()
const = 0;
341 virtual Int32 nbConstructorArg()
const = 0;
350class ARCCORE_BASE_EXPORT FactoryInfo
352 friend class Arcane::DependencyInjection::Injector;
356 explicit FactoryInfo(
const ProviderProperty& property);
360 static FactoryInfo create(
const ProviderProperty& property,
361 [[maybe_unused]]
const char* file_name,
362 [[maybe_unused]]
int line_number)
364 return FactoryInfo(property);
366 void addFactory(Ref<IInstanceFactory> f);
367 bool hasName(
const String& str)
const;
368 const FactoryInfoImpl* _impl()
const {
return m_p.get(); }
372 std::shared_ptr<FactoryInfoImpl> m_p;
383class ARCCORE_BASE_EXPORT AbstractInstanceFactory
384:
public ReferenceCounterImpl
385,
public IInstanceFactory
393template <
typename InterfaceType>
395:
public AbstractInstanceFactory
403 InstanceFactory(
const FactoryInfoImpl* si, IConcreteFactory<InterfaceType>* sub_factory)
404 : m_factory_info_impl(si)
405 , m_sub_factory(sub_factory)
409 ~InstanceFactory()
override
411 delete m_sub_factory;
414 InjectedInstanceRef createGenericReference(Injector& injector,
const String& name)
override
416 return _create(_createReference(injector), name);
419 Ref<InterfaceType> createReference(Injector& injector)
421 return _createReference(injector);
424 const FactoryInfoImpl* factoryInfoImpl()
const override
426 return m_factory_info_impl;
429 ConcreteFactoryTypeInfo concreteFactoryInfo()
const override
431 return m_sub_factory->concreteFactoryInfo();
434 Int32 nbConstructorArg()
const override
436 return m_sub_factory->nbConstructorArg();
441 const FactoryInfoImpl* m_factory_info_impl =
nullptr;
442 IConcreteFactory<InterfaceType>* m_sub_factory =
nullptr;
446 Ref<InterfaceType> _createReference(Injector& injector)
448 return m_sub_factory->createReference(injector);
451 InjectedInstanceRef _create(Ref<InterfaceType> it,
const String& name)
453 IInjectedInstance* x = (!it) ?
nullptr : new InjectedRefInstance<InterfaceType>(it, name);
454 return InjectedInstanceRef::createRef(x);
461class ARCCORE_BASE_EXPORT IConcreteFactoryBase
465 virtual ~IConcreteFactoryBase() =
default;
469 virtual ConcreteFactoryTypeInfo concreteFactoryInfo()
const = 0;
470 virtual Int32 nbConstructorArg()
const = 0;
480template <
typename InterfaceType>
482:
public IConcreteFactoryBase
486 virtual ~IConcreteFactory() =
default;
491 virtual Ref<InterfaceType> createReference(Injector&) = 0;
497class ARCCORE_BASE_EXPORT GlobalRegisterer
498:
public GenericRegisterer<GlobalRegisterer>
500 using BaseClass = GenericRegisterer<GlobalRegisterer>;
501 static BaseClass::Info m_global_registerer_info;
505 static GenericRegisterer<GlobalRegisterer>::Info& registererInfo()
507 return m_global_registerer_info;
512 typedef FactoryInfo (*FactoryCreateFunc)(
const ProviderProperty& property);
521 GlobalRegisterer(FactoryCreateFunc func,
const ProviderProperty& property)
noexcept;
525 FactoryCreateFunc infoCreatorWithPropertyFunction() {
return m_factory_create_func; }
528 const char* name() {
return m_name; }
530 const ProviderProperty& property()
const {
return m_factory_property; }
534 FactoryCreateFunc m_factory_create_func =
nullptr;
535 const char* m_name =
nullptr;
536 ProviderProperty m_factory_property;
546namespace Arcane::DependencyInjection
554class ARCCORE_BASE_EXPORT Injector
557 using FactoryFilterFunc = bool (*)(impl::IInstanceFactory*);
559 template <
class Type>
564 static IInjectedInstance* bind(
const Type& t,
const String& name)
566 return new impl::InjectedValueInstance<Type>(t, name);
568 static Type get(Injector& i,
const String& name)
570 return i._getValue<
Type>(name);
575 template <
class Po
interType>
576 class InjectorHelper<Ref<PointerType>>
580 using ThatType = Ref<PointerType>;
584 static IInjectedInstance* bind(
const ThatType& t,
const String& name)
586 return new impl::InjectedRefInstance<PointerType>(t, name);
588 static ThatType get(Injector& i,
const String& name)
590 return i._getRef<PointerType>(name);
596 class IFactoryVisitorFunctor
600 virtual ~IFactoryVisitorFunctor() =
default;
601 virtual bool execute(impl::IInstanceFactory* f) = 0;
604 template <
typename Lambda>
class FactoryVisitorFunctor
605 :
public IFactoryVisitorFunctor
609 FactoryVisitorFunctor(Lambda& lambda)
615 virtual bool execute(impl::IInstanceFactory* f) {
return m_lambda(f); }
625 class IInstanceVisitorFunctor
629 virtual ~IInstanceVisitorFunctor() =
default;
630 virtual bool execute(IInjectedInstance* v) = 0;
633 template <
typename Lambda>
class InstanceVisitorFunctor
634 :
public IInstanceVisitorFunctor
638 InstanceVisitorFunctor(Lambda& lambda)
644 virtual bool execute(IInjectedInstance* v) {
return m_lambda(v); }
654 Injector(
const Injector&) =
delete;
655 Injector& operator=(
const Injector&) =
delete;
660 template <
typename Type>
void
661 bind(
Type iref,
const String& name = String())
663 _add(InjectorHelper<Type>::bind(iref, name));
666 template <
typename Type>
Type
667 get(
const String& name = String())
669 return InjectorHelper<Type>::get(*
this, name);
685 template <
typename InterfaceType> Ref<InterfaceType>
686 createInstance(
const String& implementation_name,
bool allow_null =
false)
688 using FactoryType = impl::InstanceFactory<InterfaceType>;
689 Ref<InterfaceType> instance;
690 auto f = [&](impl::IInstanceFactory* v) ->
bool {
691 auto* t =
dynamic_cast<FactoryType*
>(v);
694 Ref<InterfaceType> x = t->createReference(*
this);
702 FactoryVisitorFunctor ff(f);
703 _iterateFactories(implementation_name, &ff);
704 if (instance.get() || allow_null)
710 auto filter_func = [](impl::IInstanceFactory* v) ->
bool {
711 return dynamic_cast<FactoryType*
>(v) !=
nullptr;
713 _printValidImplementationAndThrow(A_FUNCINFO, implementation_name, filter_func);
716 String printFactories()
const;
718 void fillWithGlobalFactories();
726 void _add(IInjectedInstance* instance);
729 void _iterateInstances(
const std::type_info& t_info,
const String& instance_name,
730 IInstanceVisitorFunctor* lambda);
731 size_t _nbValue()
const;
732 IInjectedInstance* _value(
size_t i)
const;
742 void _iterateFactories(
const String& factory_name, IFactoryVisitorFunctor* functor)
const;
743 size_t _nbFactory()
const;
744 impl::IInstanceFactory* _factory(
size_t i)
const;
747 template <
typename InterfaceType> Ref<InterfaceType>
748 _getRef(
const String& instance_name)
750 using InjectedType = impl::IInjectedRefInstanceT<InterfaceType>;
751 InjectedType* t =
nullptr;
752 auto f = [&](IInjectedInstance* v) ->
bool {
753 t =
dynamic_cast<InjectedType*
>(v);
756 InstanceVisitorFunctor ff(f);
757 _iterateInstances(
typeid(Ref<InterfaceType>), instance_name, &ff);
759 return t->instance();
761 ARCCORE_THROW(NotImplementedException,
"Create Ref<InterfaceType> from factory");
764 template <
typename Type>
Type
765 _getValue(
const String& instance_name)
767 using InjectedType = impl::IInjectedValueInstance<Type>;
768 InjectedType* t =
nullptr;
769 auto f = [&](IInjectedInstance* v) ->
bool {
770 t =
dynamic_cast<InjectedType*
>(v);
773 InstanceVisitorFunctor ff(f);
774 _iterateInstances(
typeid(
Type), instance_name, &ff);
776 return t->instance();
777 _doError(A_FUNCINFO,
"Can not find value for type");
779 [[noreturn]]
void _printValidImplementationAndThrow(
const TraceInfo& ti,
780 const String& implementation_name,
781 FactoryFilterFunc filter_func);
782 [[noreturn]]
void _doError(
const TraceInfo& ti,
const String& message);
790namespace Arcane::DependencyInjection::impl
796class ARCCORE_BASE_EXPORT ConstructorRegistererBase
800 [[noreturn]]
void _doError1(
const String& message,
int nb_value);
809template <
typename... Args>
810class ConstructorRegisterer
811:
public ConstructorRegistererBase
815 using ArgsType = std::tuple<Args...>;
817 ConstructorRegisterer() {}
820 template <std::
size_t I>
821 static auto _get(Injector& i) -> std::tuple_element_t<I, ArgsType>
823 using SelectedType = std::tuple_element_t<I, ArgsType>;
825 return i.get<SelectedType>();
828 ArgsType createTuple(Injector& i)
831 constexpr int tuple_size = std::tuple_size<ArgsType>();
832 static_assert(tuple_size < 3,
"Too many arguments for createTuple (max=2)");
833 if constexpr (tuple_size == 0) {
836 else if constexpr (tuple_size == 1) {
837 return ArgsType(_get<0>(i));
839 else if constexpr (tuple_size == 2) {
840 return ArgsType(_get<0>(i), _get<1>(i));
843 _doError1(
"Too many arguments for createTuple n={0} max=2", tuple_size);
854template <
typename InterfaceType,
typename ConcreteType,
typename ConstructorType>
858 using Args =
typename ConstructorType::ArgsType;
862 Ref<InterfaceType> createReference(Injector& injector)
override
865 ConcreteType* st = _create(ct.createTuple(injector));
866 return makeRef<InterfaceType>(st);
868 ConcreteFactoryTypeInfo concreteFactoryInfo()
const override
870 return ConcreteFactoryTypeInfo::create<InterfaceType, ConcreteType, ConstructorType>();
872 Int32 nbConstructorArg()
const override
874 return std::tuple_size<Args>();
884 ConcreteType* _create(
const Args&& tuple_args)
886 ConcreteType* st = std::apply([](
auto&&... args) -> ConcreteType* {
return new ConcreteType(args...); }, tuple_args);
898template <
typename... Interfaces>
899class InterfaceListRegisterer
909 template <
typename ConcreteType,
typename ConstructorType>
void
910 registerFactory(FactoryInfo& si)
912 _registerFactory<ConcreteType, ConstructorType, Interfaces...>(si);
917 template <
typename ConcreteType,
typename ConstructorType,
918 typename InterfaceType,
typename... OtherInterfaces>
920 _registerFactory(FactoryInfo& fi)
922 auto* factory =
new ConcreteFactory<InterfaceType, ConcreteType, ConstructorType>();
923 fi.addFactory(createRef<InstanceFactory<InterfaceType>>(fi._impl(), factory));
925 if constexpr (
sizeof...(OtherInterfaces) > 0)
926 _registerFactory<ConcreteType, ConstructorType, OtherInterfaces...>(fi);
938template <
typename ConcreteType,
typename InterfaceList>
939class InjectionRegisterer
944 template <
typename... Constructors>
void
945 registerProviderInfo(FactoryInfo& si,
const Constructors&... args)
947 _create(si, args...);
953 InterfaceList m_interface_list;
958 template <
typename ConstructorType>
void
959 _create(FactoryInfo& si,
const ConstructorType&)
961 m_interface_list.template registerFactory<ConcreteType, ConstructorType>(si);
965 template <
typename C1,
typename C2,
typename... OtherConstructors>
966 void _create(FactoryInfo& si,
const C1& c1,
const C2& c2,
const OtherConstructors&... args)
970 _create<C2, OtherConstructors...>(si, c2, args...);
982#define ARCANE_DI_CONSTRUCTOR(...) \
983 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<__VA_ARGS__>()
985#define ARCANE_DI_EMPTY_CONSTRUCTOR(...) \
986 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<>()
990#define ARCANE_DI_INTERFACES(...) \
991 ::Arcane::DependencyInjection::impl::InterfaceListRegisterer<__VA_ARGS__>
993#define ARCANE_DI_REGISTER_PROVIDER(t_class, t_provider_property, t_interfaces, ...) \
996 Arcane::DependencyInjection::impl::FactoryInfo \
997 ARCANE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class)(const Arcane::DependencyInjection::ProviderProperty& property) \
999 auto si = Arcane::DependencyInjection::impl::FactoryInfo::create(property, __FILE__, __LINE__); \
1000 Arcane::DependencyInjection::impl::InjectionRegisterer<t_class, t_interfaces> injection_registerer; \
1001 injection_registerer.registerProviderInfo(si, __VA_ARGS__); \
1005 Arcane::DependencyInjection::impl::GlobalRegisterer ARCANE_EXPORT ARCANE_JOIN_WITH_LINE(globalServiceRegisterer##aclass)(&ARCANE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class), t_provider_property)
#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.
Gestion des références à une classe C++.
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.