Arcane  v4.1.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DependencyInjection.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* DependencyInjection.h (C) 2000-2025 */
9/* */
10/* Types et fonctions pour gérer le pattern 'DependencyInjection'. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_BASE_INTERNAL_DEPENDENCYINJECTION_H
13#define ARCCORE_BASE_INTERNAL_DEPENDENCYINJECTION_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16/*
17 * NOTE: API en cours de définition.
18 * Ne pas utiliser en dehors de Arccore/Arcane
19 */
20#include "arccore/base/Ref.h"
21#include "arccore/base/ExternalRef.h"
22#include "arccore/base/GenericRegisterer.h"
24
25//TODO Mettre le lancement des exceptions dans le '.cc'
26#include "arccore/base/NotImplementedException.h"
27
28#include <tuple>
29#include <typeinfo>
30
31// TODO: Améliorer les messages d'erreurs en cas d'échec de l'injection
32// TODO: Ajouter méthodes pour afficher le type en cas d'erreur (utiliser A_FUNC_INFO)
33// TODO: Ajouter mode verbose
34// TODO: Supporter plusieurs constructeurs et ne pas échouer si le premier
35// ne fonctionne pas
36// TODO: Supporter des instances externes (comme par exemple celles créées en C#).
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41namespace Arcane::DependencyInjection
42{
43class Injector;
44}
45
46namespace Arcane::DependencyInjection::impl
47{
48class FactoryInfo;
49class FactoryInfoImpl;
50class IInstanceFactory;
51template <typename InterfaceType>
53class ConcreteFactoryTypeInfo;
54} // namespace Arcane::DependencyInjection::impl
55
56ARCCORE_DECLARE_REFERENCE_COUNTED_CLASS(Arcane::DependencyInjection::impl::IInstanceFactory)
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61namespace Arcane::DependencyInjection
62{
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67class ARCCORE_BASE_EXPORT IInjectedInstance
68{
69 public:
70 virtual ~IInjectedInstance() = default;
71 virtual bool hasName(const String& str) const = 0;
72 virtual bool hasTypeInfo(const std::type_info& tinfo) const = 0;
73};
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
83class ARCCORE_BASE_EXPORT ProviderProperty
84{
85 public:
86
87 ProviderProperty(const char* name)
88 : m_name(name)
89 {}
90
91 public:
92
93 const char* name() const { return m_name; }
94
95 private:
96
97 const char* m_name;
98};
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
102
103} // namespace Arcane::DependencyInjection
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
108namespace Arcane::DependencyInjection::impl
109{
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113
114class TypeInfo
115{
116 private:
117
118 TypeInfo(const TraceInfo& trace_info, const std::type_info& type_info)
119 : m_trace_info(trace_info)
120 , m_type_info(type_info)
121 {}
122
123 public:
124
125 template <typename Type> static TypeInfo create()
126 {
127 return TypeInfo(A_FUNCINFO, typeid(Type));
128 }
129 const TraceInfo& traceInfo() const { return m_trace_info; }
130 const std::type_info& stdTypeInfo() const { return m_type_info; }
131
132 private:
133
134 TraceInfo m_trace_info;
135 const std::type_info& m_type_info;
136};
137
138/*---------------------------------------------------------------------------*/
139/*---------------------------------------------------------------------------*/
147class ARCCORE_BASE_EXPORT ConcreteFactoryTypeInfo
148{
149 private:
150
151 ConcreteFactoryTypeInfo(TypeInfo&& a, TypeInfo&& b, TypeInfo&& c)
152 : m_interface_info(a)
153 , m_concrete_info(b)
154 , m_constructor_info(c)
155 {}
156
157 public:
158
159 template <typename InterfaceType, typename ConcreteType, typename ConstructorType>
160 static ConcreteFactoryTypeInfo create()
161 {
162 return ConcreteFactoryTypeInfo(TypeInfo::create<InterfaceType>(),
163 TypeInfo::create<ConcreteType>(),
164 TypeInfo::create<ConstructorType>());
165 }
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; }
169
170 private:
171
172 TypeInfo m_interface_info;
173 TypeInfo m_concrete_info;
174 TypeInfo m_constructor_info;
175};
176
177/*---------------------------------------------------------------------------*/
178/*---------------------------------------------------------------------------*/
183template <typename InterfaceType>
184class IInjectedRefInstanceT
185: public IInjectedInstance
186{
187 public:
188
189 virtual Ref<InterfaceType> instance() = 0;
190
191 private:
192};
193
194/*---------------------------------------------------------------------------*/
195/*---------------------------------------------------------------------------*/
200template <typename InterfaceType>
201class InjectedRefInstance
202: public IInjectedRefInstanceT<InterfaceType>
203{
204 public:
205
206 using InstanceType = Ref<InterfaceType>;
207
208 public:
209
210 InjectedRefInstance(InstanceType t_instance, const String& t_name)
211 : m_instance(t_instance)
212 , m_name(t_name)
213 {}
214
215 public:
216
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; }
220
221 private:
222
223 InstanceType m_instance;
224 String m_name;
225};
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
233template <typename Type>
234class IInjectedValueInstance
235: public IInjectedInstance
236{
237 public:
238
239 virtual Type instance() const = 0;
240};
241
242/*---------------------------------------------------------------------------*/
243/*---------------------------------------------------------------------------*/
248template <typename Type>
249class InjectedValueInstance
250: public IInjectedValueInstance<Type>
251{
252 public:
253
254 using InstanceType = Type;
255
256 public:
257
258 InjectedValueInstance(Type t_instance, const String& t_name)
259 : m_instance(t_instance)
260 , m_name(t_name)
261 {}
262
263 public:
264
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; }
268
269 private:
270
271 Type m_instance;
272 String m_name;
273};
274
275/*---------------------------------------------------------------------------*/
276/*---------------------------------------------------------------------------*/
283class ARCCORE_BASE_EXPORT InjectedInstanceRef
284{
285 typedef Ref<IInjectedInstance> RefType;
286
287 private:
288
289 explicit InjectedInstanceRef(const RefType& r)
290 : m_instance(r)
291 {}
292
293 public:
294
295 InjectedInstanceRef() = default;
296
297 public:
298
299 static InjectedInstanceRef createRef(IInjectedInstance* p)
300 {
301 return InjectedInstanceRef(RefType::create(p));
302 }
303 static InjectedInstanceRef createRefNoDestroy(IInjectedInstance* p)
304 {
305 return InjectedInstanceRef(RefType::_createNoDestroy(p));
306 }
307 static InjectedInstanceRef createWithHandle(IInjectedInstance* p, Internal::ExternalRef handle)
308 {
309 return InjectedInstanceRef(RefType::createWithHandle(p, handle));
310 }
311
312 public:
313
314 IInjectedInstance* get() const { return m_instance.get(); }
315 void reset() { m_instance.reset(); }
316
317 private:
318
319 RefType m_instance;
320};
321
322/*---------------------------------------------------------------------------*/
323/*---------------------------------------------------------------------------*/
328class ARCCORE_BASE_EXPORT IInstanceFactory
329{
331
332 protected:
333
334 virtual ~IInstanceFactory() = default;
335
336 public:
337
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;
342};
343
344/*---------------------------------------------------------------------------*/
345/*---------------------------------------------------------------------------*/
350class ARCCORE_BASE_EXPORT FactoryInfo
351{
352 friend class Arcane::DependencyInjection::Injector;
353
354 private:
355
356 explicit FactoryInfo(const ProviderProperty& property);
357
358 public:
359
360 static FactoryInfo create(const ProviderProperty& property,
361 [[maybe_unused]] const char* file_name,
362 [[maybe_unused]] int line_number)
363 {
364 return FactoryInfo(property);
365 }
366 void addFactory(Ref<IInstanceFactory> f);
367 bool hasName(const String& str) const;
368 const FactoryInfoImpl* _impl() const { return m_p.get(); }
369
370 private:
371
372 std::shared_ptr<FactoryInfoImpl> m_p;
373};
374
375/*---------------------------------------------------------------------------*/
376/*---------------------------------------------------------------------------*/
383class ARCCORE_BASE_EXPORT AbstractInstanceFactory
384: public ReferenceCounterImpl
385, public IInstanceFactory
386{
388};
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
393template <typename InterfaceType>
394class InstanceFactory
395: public AbstractInstanceFactory
396{
397 // NOTE: On ne conserve pas une instance de 'FactoryInfo'
398 // mais uniquement son implémentation pour éviter des références croisées
399 // avec le std::shared_ptr.
400
401 public:
402
403 InstanceFactory(const FactoryInfoImpl* si, IConcreteFactory<InterfaceType>* sub_factory)
404 : m_factory_info_impl(si)
405 , m_sub_factory(sub_factory)
406 {
407 }
408
409 ~InstanceFactory() override
410 {
411 delete m_sub_factory;
412 }
413
414 InjectedInstanceRef createGenericReference(Injector& injector, const String& name) override
415 {
416 return _create(_createReference(injector), name);
417 }
418
419 Ref<InterfaceType> createReference(Injector& injector)
420 {
421 return _createReference(injector);
422 }
423
424 const FactoryInfoImpl* factoryInfoImpl() const override
425 {
426 return m_factory_info_impl;
427 }
428
429 ConcreteFactoryTypeInfo concreteFactoryInfo() const override
430 {
431 return m_sub_factory->concreteFactoryInfo();
432 }
433
434 Int32 nbConstructorArg() const override
435 {
436 return m_sub_factory->nbConstructorArg();
437 }
438
439 protected:
440
441 const FactoryInfoImpl* m_factory_info_impl = nullptr;
442 IConcreteFactory<InterfaceType>* m_sub_factory = nullptr;
443
444 private:
445
446 Ref<InterfaceType> _createReference(Injector& injector)
447 {
448 return m_sub_factory->createReference(injector);
449 }
450
451 InjectedInstanceRef _create(Ref<InterfaceType> it, const String& name)
452 {
453 IInjectedInstance* x = (!it) ? nullptr : new InjectedRefInstance<InterfaceType>(it, name);
454 return InjectedInstanceRef::createRef(x);
455 }
456};
457
458/*---------------------------------------------------------------------------*/
459/*---------------------------------------------------------------------------*/
460
461class ARCCORE_BASE_EXPORT IConcreteFactoryBase
462{
463 public:
464
465 virtual ~IConcreteFactoryBase() = default;
466
467 public:
468
469 virtual ConcreteFactoryTypeInfo concreteFactoryInfo() const = 0;
470 virtual Int32 nbConstructorArg() const = 0;
471};
472
473/*---------------------------------------------------------------------------*/
474/*---------------------------------------------------------------------------*/
480template <typename InterfaceType>
482: public IConcreteFactoryBase
483{
484 public:
485
486 virtual ~IConcreteFactory() = default;
487
488 public:
489
491 virtual Ref<InterfaceType> createReference(Injector&) = 0;
492};
493
494/*---------------------------------------------------------------------------*/
495/*---------------------------------------------------------------------------*/
496
497class ARCCORE_BASE_EXPORT GlobalRegisterer
498: public GenericRegisterer<GlobalRegisterer>
499{
500 using BaseClass = GenericRegisterer<GlobalRegisterer>;
501 static BaseClass::Info m_global_registerer_info;
502
503 public:
504
505 static GenericRegisterer<GlobalRegisterer>::Info& registererInfo()
506 {
507 return m_global_registerer_info;
508 }
509
510 public:
511
512 typedef FactoryInfo (*FactoryCreateFunc)(const ProviderProperty& property);
513
514 public:
515
521 GlobalRegisterer(FactoryCreateFunc func, const ProviderProperty& property) noexcept;
522
523 public:
524
525 FactoryCreateFunc infoCreatorWithPropertyFunction() { return m_factory_create_func; }
526
528 const char* name() { return m_name; }
529
530 const ProviderProperty& property() const { return m_factory_property; }
531
532 private:
533
534 FactoryCreateFunc m_factory_create_func = nullptr;
535 const char* m_name = nullptr;
536 ProviderProperty m_factory_property;
537
538 private:
539};
540
541/*---------------------------------------------------------------------------*/
542/*---------------------------------------------------------------------------*/
543
544} // namespace Arcane::DependencyInjection::impl
545
546namespace Arcane::DependencyInjection
547{
548
549/*---------------------------------------------------------------------------*/
550/*---------------------------------------------------------------------------*/
554class ARCCORE_BASE_EXPORT Injector
555{
556 class Impl;
557 using FactoryFilterFunc = bool (*)(impl::IInstanceFactory*);
558
559 template <class Type>
560 class InjectorHelper
561 {
562 public:
563
564 static IInjectedInstance* bind(const Type& t, const String& name)
565 {
566 return new impl::InjectedValueInstance<Type>(t, name);
567 }
568 static Type get(Injector& i, const String& name)
569 {
570 return i._getValue<Type>(name);
571 }
572 };
573
575 template <class PointerType>
576 class InjectorHelper<Ref<PointerType>>
577 {
578 public:
579
580 using ThatType = Ref<PointerType>;
581
582 public:
583
584 static IInjectedInstance* bind(const ThatType& t, const String& name)
585 {
586 return new impl::InjectedRefInstance<PointerType>(t, name);
587 }
588 static ThatType get(Injector& i, const String& name)
589 {
590 return i._getRef<PointerType>(name);
591 }
592 };
596 class IFactoryVisitorFunctor
597 {
598 public:
599
600 virtual ~IFactoryVisitorFunctor() = default;
601 virtual bool execute(impl::IInstanceFactory* f) = 0;
602 };
603
604 template <typename Lambda> class FactoryVisitorFunctor
605 : public IFactoryVisitorFunctor
606 {
607 public:
608
609 FactoryVisitorFunctor(Lambda& lambda)
610 : m_lambda(lambda)
611 {}
612
613 public:
614
615 virtual bool execute(impl::IInstanceFactory* f) { return m_lambda(f); }
616
617 private:
618
619 Lambda& m_lambda;
620 };
621
625 class IInstanceVisitorFunctor
626 {
627 public:
628
629 virtual ~IInstanceVisitorFunctor() = default;
630 virtual bool execute(IInjectedInstance* v) = 0;
631 };
632
633 template <typename Lambda> class InstanceVisitorFunctor
634 : public IInstanceVisitorFunctor
635 {
636 public:
637
638 InstanceVisitorFunctor(Lambda& lambda)
639 : m_lambda(lambda)
640 {}
641
642 public:
643
644 virtual bool execute(IInjectedInstance* v) { return m_lambda(v); }
645
646 private:
647
648 Lambda& m_lambda;
649 };
650
651 public:
652
653 Injector();
654 Injector(const Injector&) = delete;
655 Injector& operator=(const Injector&) = delete;
656 ~Injector();
657
658 public:
659
660 template <typename Type> void
661 bind(Type iref, const String& name = String())
662 {
663 _add(InjectorHelper<Type>::bind(iref, name));
664 }
665
666 template <typename Type> Type
667 get(const String& name = String())
668 {
669 return InjectorHelper<Type>::get(*this, name);
670 }
671
685 template <typename InterfaceType> Ref<InterfaceType>
686 createInstance(const String& implementation_name, bool allow_null = false)
687 {
688 using FactoryType = impl::InstanceFactory<InterfaceType>;
689 Ref<InterfaceType> instance;
690 auto f = [&](impl::IInstanceFactory* v) -> bool {
691 auto* t = dynamic_cast<FactoryType*>(v);
692 //std::cout << "TRY DYNAMIC_CAST FACTORY v=" << v << " t=" << t << "\n";
693 if (t) {
694 Ref<InterfaceType> x = t->createReference(*this);
695 if (x.get()) {
696 instance = x;
697 return true;
698 }
699 }
700 return false;
701 };
702 FactoryVisitorFunctor ff(f);
703 _iterateFactories(implementation_name, &ff);
704 if (instance.get() || allow_null)
705 return instance;
706
707 // Pas d'implémentation correspondante trouvée.
708 // Dans ce cas on récupère la liste des implémentations valides et on les affiche dans
709 // le message d'erreur.
710 auto filter_func = [](impl::IInstanceFactory* v) -> bool {
711 return dynamic_cast<FactoryType*>(v) != nullptr;
712 };
713 _printValidImplementationAndThrow(A_FUNCINFO, implementation_name, filter_func);
714 }
715
716 String printFactories() const;
717
718 void fillWithGlobalFactories();
719
720 private:
721
722 Impl* m_p = nullptr;
723
724 private:
725
726 void _add(IInjectedInstance* instance);
727
728 // Itère sur la lambda et s'arrête dès que cette dernière retourne \a true
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;
733
742 void _iterateFactories(const String& factory_name, IFactoryVisitorFunctor* functor) const;
743 size_t _nbFactory() const;
744 impl::IInstanceFactory* _factory(size_t i) const;
745
746 // Spécialisation pour les références
747 template <typename InterfaceType> Ref<InterfaceType>
748 _getRef(const String& instance_name)
749 {
750 using InjectedType = impl::IInjectedRefInstanceT<InterfaceType>;
751 InjectedType* t = nullptr;
752 auto f = [&](IInjectedInstance* v) -> bool {
753 t = dynamic_cast<InjectedType*>(v);
754 return t;
755 };
756 InstanceVisitorFunctor ff(f);
757 _iterateInstances(typeid(Ref<InterfaceType>), instance_name, &ff);
758 if (t)
759 return t->instance();
760 // TODO: faire un fatal ou créer l'instance
761 ARCCORE_THROW(NotImplementedException, "Create Ref<InterfaceType> from factory");
762 }
763
764 template <typename Type> Type
765 _getValue(const String& instance_name)
766 {
767 using InjectedType = impl::IInjectedValueInstance<Type>;
768 InjectedType* t = nullptr;
769 auto f = [&](IInjectedInstance* v) -> bool {
770 t = dynamic_cast<InjectedType*>(v);
771 return t;
772 };
773 InstanceVisitorFunctor ff(f);
774 _iterateInstances(typeid(Type), instance_name, &ff);
775 if (t)
776 return t->instance();
777 _doError(A_FUNCINFO, "Can not find value for type");
778 }
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);
783};
784
785/*---------------------------------------------------------------------------*/
786/*---------------------------------------------------------------------------*/
787
788} // namespace Arcane::DependencyInjection
789
790namespace Arcane::DependencyInjection::impl
791{
792
793/*---------------------------------------------------------------------------*/
794/*---------------------------------------------------------------------------*/
795
796class ARCCORE_BASE_EXPORT ConstructorRegistererBase
797{
798 protected:
799
800 [[noreturn]] void _doError1(const String& message, int nb_value);
801};
802
809template <typename... Args>
810class ConstructorRegisterer
811: public ConstructorRegistererBase
812{
813 public:
814
815 using ArgsType = std::tuple<Args...>;
816
817 ConstructorRegisterer() {}
818
819 // Permet de récupérer via l'injecteur \a i le I-ème argument du tuple.
820 template <std::size_t I>
821 static auto _get(Injector& i) -> std::tuple_element_t<I, ArgsType>
822 {
823 using SelectedType = std::tuple_element_t<I, ArgsType>;
824 //std::cout << "RETURN _GET(I=" << I << ")\n";
825 return i.get<SelectedType>();
826 }
827
828 ArgsType createTuple(Injector& i)
829 {
830 // TODO: supporter plus d'arguments ou passer à des 'variadic templates'
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) {
834 return ArgsType();
835 }
836 else if constexpr (tuple_size == 1) {
837 return ArgsType(_get<0>(i));
838 }
839 else if constexpr (tuple_size == 2) {
840 return ArgsType(_get<0>(i), _get<1>(i));
841 }
842 // Ne devrait pas arriver mais on ne sais jamais.
843 _doError1("Too many arguments for createTuple n={0} max=2", tuple_size);
844 }
845};
846
847/*---------------------------------------------------------------------------*/
848/*---------------------------------------------------------------------------*/
854template <typename InterfaceType, typename ConcreteType, typename ConstructorType>
855class ConcreteFactory
856: public IConcreteFactory<InterfaceType>
857{
858 using Args = typename ConstructorType::ArgsType;
859
860 public:
861
862 Ref<InterfaceType> createReference(Injector& injector) override
863 {
864 ConstructorType ct;
865 ConcreteType* st = _create(ct.createTuple(injector));
866 return makeRef<InterfaceType>(st);
867 }
868 ConcreteFactoryTypeInfo concreteFactoryInfo() const override
869 {
870 return ConcreteFactoryTypeInfo::create<InterfaceType, ConcreteType, ConstructorType>();
871 }
872 Int32 nbConstructorArg() const override
873 {
874 return std::tuple_size<Args>();
875 }
876
877 private:
878
884 ConcreteType* _create(const Args&& tuple_args)
885 {
886 ConcreteType* st = std::apply([](auto&&... args) -> ConcreteType* { return new ConcreteType(args...); }, tuple_args);
887 return st;
888 }
889};
890
891/*---------------------------------------------------------------------------*/
892/*---------------------------------------------------------------------------*/
898template <typename... Interfaces>
899class InterfaceListRegisterer
900{
901 public:
902
909 template <typename ConcreteType, typename ConstructorType> void
910 registerFactory(FactoryInfo& si)
911 {
912 _registerFactory<ConcreteType, ConstructorType, Interfaces...>(si);
913 }
914
915 private:
916
917 template <typename ConcreteType, typename ConstructorType,
918 typename InterfaceType, typename... OtherInterfaces>
919 void
920 _registerFactory(FactoryInfo& fi)
921 {
922 auto* factory = new ConcreteFactory<InterfaceType, ConcreteType, ConstructorType>();
923 fi.addFactory(createRef<InstanceFactory<InterfaceType>>(fi._impl(), factory));
924 // Applique récursivement pour les autres interfaces si nécessaire
925 if constexpr (sizeof...(OtherInterfaces) > 0)
926 _registerFactory<ConcreteType, ConstructorType, OtherInterfaces...>(fi);
927 }
928};
929
930/*---------------------------------------------------------------------------*/
931/*---------------------------------------------------------------------------*/
938template <typename ConcreteType, typename InterfaceList>
939class InjectionRegisterer
940{
941 public:
942
944 template <typename... Constructors> void
945 registerProviderInfo(FactoryInfo& si, const Constructors&... args)
946 {
947 _create(si, args...);
948 }
949
950 private:
951
952 // TODO: Créér l'instance de 'FactoryInfo' dans le constructeur
953 InterfaceList m_interface_list;
954
955 private:
956
958 template <typename ConstructorType> void
959 _create(FactoryInfo& si, const ConstructorType&)
960 {
961 m_interface_list.template registerFactory<ConcreteType, ConstructorType>(si);
962 }
963
965 template <typename C1, typename C2, typename... OtherConstructors>
966 void _create(FactoryInfo& si, const C1& c1, const C2& c2, const OtherConstructors&... args)
967 {
968 _create<C1>(si, c1);
969 // Applique la récursivité sur les types restants
970 _create<C2, OtherConstructors...>(si, c2, args...);
971 }
972};
973
974/*---------------------------------------------------------------------------*/
975/*---------------------------------------------------------------------------*/
976
977} // namespace Arcane::DependencyInjection::impl
978
979/*---------------------------------------------------------------------------*/
980/*---------------------------------------------------------------------------*/
981
982#define ARCANE_DI_CONSTRUCTOR(...) \
983 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<__VA_ARGS__>()
984
985#define ARCANE_DI_EMPTY_CONSTRUCTOR(...) \
986 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<>()
987
988// TODO: garantir au moins une interface
989
990#define ARCANE_DI_INTERFACES(...) \
991 ::Arcane::DependencyInjection::impl::InterfaceListRegisterer<__VA_ARGS__>
992
993#define ARCANE_DI_REGISTER_PROVIDER(t_class, t_provider_property, t_interfaces, ...) \
994 namespace \
995 { \
996 Arcane::DependencyInjection::impl::FactoryInfo \
997 ARCANE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class)(const Arcane::DependencyInjection::ProviderProperty& property) \
998 { \
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__); \
1002 return si; \
1003 } \
1004 } \
1005 Arcane::DependencyInjection::impl::GlobalRegisterer ARCANE_EXPORT ARCANE_JOIN_WITH_LINE(globalServiceRegisterer##aclass)(&ARCANE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class), t_provider_property)
1006
1007/*---------------------------------------------------------------------------*/
1008/*---------------------------------------------------------------------------*/
1009
1010#endif
#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.
Type
Type of JSON value.
Definition rapidjson.h:730