Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
DependencyInjection.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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 and functions to manage the 'DependencyInjection' pattern. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_BASE_INTERNAL_DEPENDENCYINJECTION_H
13#define ARCCORE_BASE_INTERNAL_DEPENDENCYINJECTION_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17/*
18 * NOTE: API is currently being defined.
19 * Do not use outside of Arccore/Arcane
20 */
21#include "arccore/base/Ref.h"
22#include "arccore/base/ExternalRef.h"
23#include "arccore/base/GenericRegisterer.h"
25
26//TODO Put the exception throwing in the '.cc'
27#include "arccore/base/NotImplementedException.h"
28
29#include <tuple>
30#include <typeinfo>
31
32// TODO: Improve error messages in case of injection failure
33// TODO: Add methods to display the type in case of error (use A_FUNC_INFO)
34// TODO: Add verbose mode
35// TODO: Support multiple constructors and do not fail if the first
36// does not work
37// TODO: Support external instances (such as those created in C#).
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42namespace Arcane::DependencyInjection
43{
44class Injector;
45}
46
47namespace Arcane::DependencyInjection::impl
48{
49class FactoryInfo;
50class FactoryInfoImpl;
51class IInstanceFactory;
52template <typename InterfaceType>
54class ConcreteFactoryTypeInfo;
55} // namespace Arcane::DependencyInjection::impl
56
57ARCCORE_DECLARE_REFERENCE_COUNTED_CLASS(Arcane::DependencyInjection::impl::IInstanceFactory)
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62namespace Arcane::DependencyInjection
63{
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68class ARCCORE_BASE_EXPORT IInjectedInstance
69{
70 public:
71
72 virtual ~IInjectedInstance() = default;
73 virtual bool hasName(const String& str) const = 0;
74 virtual bool hasTypeInfo(const std::type_info& tinfo) const = 0;
75};
76
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79
85class ARCCORE_BASE_EXPORT ProviderProperty
86{
87 public:
88
89 ProviderProperty(const char* name)
90 : m_name(name)
91 {}
92
93 public:
94
95 const char* name() const { return m_name; }
96
97 private:
98
99 const char* m_name;
100};
101
102/*---------------------------------------------------------------------------*/
103/*---------------------------------------------------------------------------*/
104
105} // namespace Arcane::DependencyInjection
106
107/*---------------------------------------------------------------------------*/
108/*---------------------------------------------------------------------------*/
109
110namespace Arcane::DependencyInjection::impl
111{
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
115
116class TypeInfo
117{
118 private:
119
120 TypeInfo(const TraceInfo& trace_info, const std::type_info& type_info)
121 : m_trace_info(trace_info)
122 , m_type_info(type_info)
123 {}
124
125 public:
126
127 template <typename Type> static TypeInfo create()
128 {
129 return TypeInfo(A_FUNCINFO, typeid(Type));
130 }
131 const TraceInfo& traceInfo() const { return m_trace_info; }
132 const std::type_info& stdTypeInfo() const { return m_type_info; }
133
134 private:
135
136 TraceInfo m_trace_info;
137 const std::type_info& m_type_info;
138};
139
140/*---------------------------------------------------------------------------*/
141/*---------------------------------------------------------------------------*/
142
150class ARCCORE_BASE_EXPORT ConcreteFactoryTypeInfo
151{
152 private:
153
154 ConcreteFactoryTypeInfo(TypeInfo&& a, TypeInfo&& b, TypeInfo&& c)
155 : m_interface_info(a)
156 , m_concrete_info(b)
157 , m_constructor_info(c)
158 {}
159
160 public:
161
162 template <typename InterfaceType, typename ConcreteType, typename ConstructorType>
163 static ConcreteFactoryTypeInfo create()
164 {
165 return ConcreteFactoryTypeInfo(TypeInfo::create<InterfaceType>(),
166 TypeInfo::create<ConcreteType>(),
167 TypeInfo::create<ConstructorType>());
168 }
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; }
172
173 private:
174
175 TypeInfo m_interface_info;
176 TypeInfo m_concrete_info;
177 TypeInfo m_constructor_info;
178};
179
180/*---------------------------------------------------------------------------*/
181/*---------------------------------------------------------------------------*/
182
187template <typename InterfaceType>
188class IInjectedRefInstanceT
189: public IInjectedInstance
190{
191 public:
192
193 virtual Ref<InterfaceType> instance() = 0;
194
195 private:
196};
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200
205template <typename InterfaceType>
206class InjectedRefInstance
207: public IInjectedRefInstanceT<InterfaceType>
208{
209 public:
210
211 using InstanceType = Ref<InterfaceType>;
212
213 public:
214
215 InjectedRefInstance(InstanceType t_instance, const String& t_name)
216 : m_instance(t_instance)
217 , m_name(t_name)
218 {}
219
220 public:
221
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; }
225
226 private:
227
228 InstanceType m_instance;
229 String m_name;
230};
231
232/*---------------------------------------------------------------------------*/
233/*---------------------------------------------------------------------------*/
234
239template <typename Type>
240class IInjectedValueInstance
241: public IInjectedInstance
242{
243 public:
244
245 virtual Type instance() const = 0;
246};
247
248/*---------------------------------------------------------------------------*/
249/*---------------------------------------------------------------------------*/
250
255template <typename Type>
256class InjectedValueInstance
257: public IInjectedValueInstance<Type>
258{
259 public:
260
261 using InstanceType = Type;
262
263 public:
264
265 InjectedValueInstance(Type t_instance, const String& t_name)
266 : m_instance(t_instance)
267 , m_name(t_name)
268 {}
269
270 public:
271
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; }
275
276 private:
277
278 Type m_instance;
279 String m_name;
280};
281
282/*---------------------------------------------------------------------------*/
283/*---------------------------------------------------------------------------*/
284
291class ARCCORE_BASE_EXPORT InjectedInstanceRef
292{
293 typedef Ref<IInjectedInstance> RefType;
294
295 private:
296
297 explicit InjectedInstanceRef(const RefType& r)
298 : m_instance(r)
299 {}
300
301 public:
302
303 InjectedInstanceRef() = default;
304
305 public:
306
307 static InjectedInstanceRef createRef(IInjectedInstance* p)
308 {
309 return InjectedInstanceRef(RefType::create(p));
310 }
311 static InjectedInstanceRef createRefNoDestroy(IInjectedInstance* p)
312 {
313 return InjectedInstanceRef(RefType::_createNoDestroy(p));
314 }
315 static InjectedInstanceRef createWithHandle(IInjectedInstance* p, Internal::ExternalRef handle)
316 {
317 return InjectedInstanceRef(RefType::createWithHandle(p, handle));
318 }
319
320 public:
321
322 IInjectedInstance* get() const { return m_instance.get(); }
323 void reset() { m_instance.reset(); }
324
325 private:
326
327 RefType m_instance;
328};
329
330/*---------------------------------------------------------------------------*/
331/*---------------------------------------------------------------------------*/
332
337class ARCCORE_BASE_EXPORT IInstanceFactory
338{
340
341 protected:
342
343 virtual ~IInstanceFactory() = default;
344
345 public:
346
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;
351};
352
353/*---------------------------------------------------------------------------*/
354/*---------------------------------------------------------------------------*/
355
360class ARCCORE_BASE_EXPORT FactoryInfo
361{
362 friend class Arcane::DependencyInjection::Injector;
363
364 private:
365
366 explicit FactoryInfo(const ProviderProperty& property);
367
368 public:
369
370 static FactoryInfo create(const ProviderProperty& property,
371 [[maybe_unused]] const char* file_name,
372 [[maybe_unused]] int line_number)
373 {
374 return FactoryInfo(property);
375 }
376 void addFactory(Ref<IInstanceFactory> f);
377 bool hasName(const String& str) const;
378 const FactoryInfoImpl* _impl() const { return m_p.get(); }
379
380 private:
381
382 std::shared_ptr<FactoryInfoImpl> m_p;
383};
384
385/*---------------------------------------------------------------------------*/
386/*---------------------------------------------------------------------------*/
387
394class ARCCORE_BASE_EXPORT AbstractInstanceFactory
395: public ReferenceCounterImpl
396, public IInstanceFactory
397{
399};
400
401/*---------------------------------------------------------------------------*/
402/*---------------------------------------------------------------------------*/
403
404template <typename InterfaceType>
405class InstanceFactory
406: public AbstractInstanceFactory
407{
408 // NOTE: We do not keep an instance of 'FactoryInfo'
409 // but only its implementation to avoid cross-references
410 // with std::shared_ptr.
411
412 public:
413
414 InstanceFactory(const FactoryInfoImpl* si, IConcreteFactory<InterfaceType>* sub_factory)
415 : m_factory_info_impl(si)
416 , m_sub_factory(sub_factory)
417 {
418 }
419
420 ~InstanceFactory() override
421 {
422 delete m_sub_factory;
423 }
424
425 InjectedInstanceRef createGenericReference(Injector& injector, const String& name) override
426 {
427 return _create(_createReference(injector), name);
428 }
429
430 Ref<InterfaceType> createReference(Injector& injector)
431 {
432 return _createReference(injector);
433 }
434
435 const FactoryInfoImpl* factoryInfoImpl() const override
436 {
437 return m_factory_info_impl;
438 }
439
440 ConcreteFactoryTypeInfo concreteFactoryInfo() const override
441 {
442 return m_sub_factory->concreteFactoryInfo();
443 }
444
445 Int32 nbConstructorArg() const override
446 {
447 return m_sub_factory->nbConstructorArg();
448 }
449
450 protected:
451
452 const FactoryInfoImpl* m_factory_info_impl = nullptr;
453 IConcreteFactory<InterfaceType>* m_sub_factory = nullptr;
454
455 private:
456
457 Ref<InterfaceType> _createReference(Injector& injector)
458 {
459 return m_sub_factory->createReference(injector);
460 }
461
462 InjectedInstanceRef _create(Ref<InterfaceType> it, const String& name)
463 {
464 IInjectedInstance* x = (!it) ? nullptr : new InjectedRefInstance<InterfaceType>(it, name);
465 return InjectedInstanceRef::createRef(x);
466 }
467};
468
469/*---------------------------------------------------------------------------*/
470/*---------------------------------------------------------------------------*/
471
472class ARCCORE_BASE_EXPORT IConcreteFactoryBase
473{
474 public:
475
476 virtual ~IConcreteFactoryBase() = default;
477
478 public:
479
480 virtual ConcreteFactoryTypeInfo concreteFactoryInfo() const = 0;
481 virtual Int32 nbConstructorArg() const = 0;
482};
483
484/*---------------------------------------------------------------------------*/
485/*---------------------------------------------------------------------------*/
486
492template <typename InterfaceType>
494: public IConcreteFactoryBase
495{
496 public:
497
498 virtual ~IConcreteFactory() = default;
499
500 public:
501
503 virtual Ref<InterfaceType> createReference(Injector&) = 0;
504};
505
506/*---------------------------------------------------------------------------*/
507/*---------------------------------------------------------------------------*/
508
509class ARCCORE_BASE_EXPORT GlobalRegisterer
510: public GenericRegisterer<GlobalRegisterer>
511{
512 using BaseClass = GenericRegisterer<GlobalRegisterer>;
513 static BaseClass::Info m_global_registerer_info;
514
515 public:
516
517 static GenericRegisterer<GlobalRegisterer>::Info& registererInfo()
518 {
519 return m_global_registerer_info;
520 }
521
522 public:
523
524 typedef FactoryInfo (*FactoryCreateFunc)(const ProviderProperty& property);
525
526 public:
527
533 GlobalRegisterer(FactoryCreateFunc func, const ProviderProperty& property) noexcept;
534
535 public:
536
537 FactoryCreateFunc infoCreatorWithPropertyFunction() { return m_factory_create_func; }
538
540 const char* name() { return m_name; }
541
542 const ProviderProperty& property() const { return m_factory_property; }
543
544 private:
545
546 FactoryCreateFunc m_factory_create_func = nullptr;
547 const char* m_name = nullptr;
548 ProviderProperty m_factory_property;
549
550 private:
551};
552
553/*---------------------------------------------------------------------------*/
554/*---------------------------------------------------------------------------*/
555
556} // namespace Arcane::DependencyInjection::impl
557
558namespace Arcane::DependencyInjection
559{
560
561/*---------------------------------------------------------------------------*/
562/*---------------------------------------------------------------------------*/
563
567class ARCCORE_BASE_EXPORT Injector
568{
569 class Impl;
570 using FactoryFilterFunc = bool (*)(impl::IInstanceFactory*);
571
572 template <class Type>
573 class InjectorHelper
574 {
575 public:
576
577 static IInjectedInstance* bind(const Type& t, const String& name)
578 {
579 return new impl::InjectedValueInstance<Type>(t, name);
580 }
581 static Type get(Injector& i, const String& name)
582 {
583 return i._getValue<Type>(name);
584 }
585 };
586
588 template <class PointerType>
589 class InjectorHelper<Ref<PointerType>>
590 {
591 public:
592
593 using ThatType = Ref<PointerType>;
594
595 public:
596
597 static IInjectedInstance* bind(const ThatType& t, const String& name)
598 {
599 return new impl::InjectedRefInstance<PointerType>(t, name);
600 }
601 static ThatType get(Injector& i, const String& name)
602 {
603 return i._getRef<PointerType>(name);
604 }
605 };
606
610 class IFactoryVisitorFunctor
611 {
612 public:
613
614 virtual ~IFactoryVisitorFunctor() = default;
615 virtual bool execute(impl::IInstanceFactory* f) = 0;
616 };
617
618 template <typename Lambda> class FactoryVisitorFunctor
619 : public IFactoryVisitorFunctor
620 {
621 public:
622
623 FactoryVisitorFunctor(Lambda& lambda)
624 : m_lambda(lambda)
625 {}
626
627 public:
628
629 virtual bool execute(impl::IInstanceFactory* f) { return m_lambda(f); }
630
631 private:
632
633 Lambda& m_lambda;
634 };
635
639 class IInstanceVisitorFunctor
640 {
641 public:
642
643 virtual ~IInstanceVisitorFunctor() = default;
644 virtual bool execute(IInjectedInstance* v) = 0;
645 };
646
647 template <typename Lambda> class InstanceVisitorFunctor
648 : public IInstanceVisitorFunctor
649 {
650 public:
651
652 InstanceVisitorFunctor(Lambda& lambda)
653 : m_lambda(lambda)
654 {}
655
656 public:
657
658 virtual bool execute(IInjectedInstance* v) { return m_lambda(v); }
659
660 private:
661
662 Lambda& m_lambda;
663 };
664
665 public:
666
667 Injector();
668 Injector(const Injector&) = delete;
669 Injector& operator=(const Injector&) = delete;
670 ~Injector();
671
672 public:
673
674 template <typename Type> void
675 bind(Type iref, const String& name = String())
676 {
677 _add(InjectorHelper<Type>::bind(iref, name));
678 }
679
680 template <typename Type> Type
681 get(const String& name = String())
682 {
683 return InjectorHelper<Type>::get(*this, name);
684 }
685
699 template <typename InterfaceType> Ref<InterfaceType>
700 createInstance(const String& implementation_name, bool allow_null = false)
701 {
702 using FactoryType = impl::InstanceFactory<InterfaceType>;
703 Ref<InterfaceType> instance;
704 auto f = [&](impl::IInstanceFactory* v) -> bool {
705 auto* t = dynamic_cast<FactoryType*>(v);
706 //std::cout << "TRY DYNAMIC_CAST FACTORY v=" << v << " t=" << t << "\n";
707 if (t) {
708 Ref<InterfaceType> x = t->createReference(*this);
709 if (x.get()) {
710 instance = x;
711 return true;
712 }
713 }
714 return false;
715 };
716 FactoryVisitorFunctor ff(f);
717 _iterateFactories(implementation_name, &ff);
718 if (instance.get() || allow_null)
719 return instance;
720
721 // No corresponding implementation found.
722 // In this case, we retrieve the list of valid implementations
723 // and display them in the error message.
724 auto filter_func = [](impl::IInstanceFactory* v) -> bool {
725 return dynamic_cast<FactoryType*>(v) != nullptr;
726 };
727 _printValidImplementationAndThrow(A_FUNCINFO, implementation_name, filter_func);
728 }
729
730 String printFactories() const;
731
732 void fillWithGlobalFactories();
733
734 private:
735
736 Impl* m_p = nullptr;
737
738 private:
739
740 void _add(IInjectedInstance* instance);
741
742 // Iterates over the lambda and stops as soon as it returns \a true
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;
747
756 void _iterateFactories(const String& factory_name, IFactoryVisitorFunctor* functor) const;
757 size_t _nbFactory() const;
758 impl::IInstanceFactory* _factory(size_t i) const;
759
760 // Specialization for references
761 template <typename InterfaceType> Ref<InterfaceType>
762 _getRef(const String& instance_name)
763 {
764 using InjectedType = impl::IInjectedRefInstanceT<InterfaceType>;
765 InjectedType* t = nullptr;
766 auto f = [&](IInjectedInstance* v) -> bool {
767 t = dynamic_cast<InjectedType*>(v);
768 return t;
769 };
770 InstanceVisitorFunctor ff(f);
771 _iterateInstances(typeid(Ref<InterfaceType>), instance_name, &ff);
772 if (t)
773 return t->instance();
774 // TODO: throw fatal or create the instance
775 ARCCORE_THROW(NotImplementedException, "Create Ref<InterfaceType> from factory");
776 }
777
778 template <typename Type> Type
779 _getValue(const String& instance_name)
780 {
781 using InjectedType = impl::IInjectedValueInstance<Type>;
782 InjectedType* t = nullptr;
783 auto f = [&](IInjectedInstance* v) -> bool {
784 t = dynamic_cast<InjectedType*>(v);
785 return t;
786 };
787 InstanceVisitorFunctor ff(f);
788 _iterateInstances(typeid(Type), instance_name, &ff);
789 if (t)
790 return t->instance();
791 _doError(A_FUNCINFO, "Can not find value for type");
792 }
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);
797};
798
799/*---------------------------------------------------------------------------*/
800/*---------------------------------------------------------------------------*/
801
802} // namespace Arcane::DependencyInjection
803
804namespace Arcane::DependencyInjection::impl
805{
806
807/*---------------------------------------------------------------------------*/
808/*---------------------------------------------------------------------------*/
809
810class ARCCORE_BASE_EXPORT ConstructorRegistererBase
811{
812 protected:
813
814 [[noreturn]] void _doError1(const String& message, int nb_value);
815};
816
823template <typename... Args>
824class ConstructorRegisterer
825: public ConstructorRegistererBase
826{
827 public:
828
829 using ArgsType = std::tuple<Args...>;
830
831 ConstructorRegisterer() {}
832
833 // Allows retrieving the I-th argument of the tuple via the injector \a i.
834 template <std::size_t I>
835 static auto _get(Injector& i) -> std::tuple_element_t<I, ArgsType>
836 {
837 using SelectedType = std::tuple_element_t<I, ArgsType>;
838 //std::cout << "RETURN _GET(I=" << I << ")\n";
839 return i.get<SelectedType>();
840 }
841
842 ArgsType createTuple(Injector& i)
843 {
844 // TODO: support more arguments or switch to 'variadic templates'
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) {
848 return ArgsType();
849 }
850 else if constexpr (tuple_size == 1) {
851 return ArgsType(_get<0>(i));
852 }
853 else if constexpr (tuple_size == 2) {
854 return ArgsType(_get<0>(i), _get<1>(i));
855 }
856 // Should not happen but you never know.
857 _doError1("Too many arguments for createTuple n={0} max=2", tuple_size);
858 }
859};
860
861/*---------------------------------------------------------------------------*/
862/*---------------------------------------------------------------------------*/
863
869template <typename InterfaceType, typename ConcreteType, typename ConstructorType>
870class ConcreteFactory
871: public IConcreteFactory<InterfaceType>
872{
873 using Args = typename ConstructorType::ArgsType;
874
875 public:
876
877 Ref<InterfaceType> createReference(Injector& injector) override
878 {
879 ConstructorType ct;
880 ConcreteType* st = _create(ct.createTuple(injector));
881 return makeRef<InterfaceType>(st);
882 }
883 ConcreteFactoryTypeInfo concreteFactoryInfo() const override
884 {
885 return ConcreteFactoryTypeInfo::create<InterfaceType, ConcreteType, ConstructorType>();
886 }
887 Int32 nbConstructorArg() const override
888 {
889 return std::tuple_size<Args>();
890 }
891
892 private:
893
899 ConcreteType* _create(const Args&& tuple_args)
900 {
901 ConcreteType* st = std::apply([](auto&&... args) -> ConcreteType* { return new ConcreteType(args...); }, tuple_args);
902 return st;
903 }
904};
905
906/*---------------------------------------------------------------------------*/
907/*---------------------------------------------------------------------------*/
908
914template <typename... Interfaces>
915class InterfaceListRegisterer
916{
917 public:
918
925 template <typename ConcreteType, typename ConstructorType> void
926 registerFactory(FactoryInfo& si)
927 {
928 _registerFactory<ConcreteType, ConstructorType, Interfaces...>(si);
929 }
930
931 private:
932
933 template <typename ConcreteType, typename ConstructorType,
934 typename InterfaceType, typename... OtherInterfaces>
935 void
936 _registerFactory(FactoryInfo& fi)
937 {
938 auto* factory = new ConcreteFactory<InterfaceType, ConcreteType, ConstructorType>();
939 fi.addFactory(createRef<InstanceFactory<InterfaceType>>(fi._impl(), factory));
940 // Recursively applies for other interfaces if necessary
941 if constexpr (sizeof...(OtherInterfaces) > 0)
942 _registerFactory<ConcreteType, ConstructorType, OtherInterfaces...>(fi);
943 }
944};
945
946/*---------------------------------------------------------------------------*/
947/*---------------------------------------------------------------------------*/
948
955template <typename ConcreteType, typename InterfaceList>
956class InjectionRegisterer
957{
958 public:
959
961 template <typename... Constructors> void
962 registerProviderInfo(FactoryInfo& si, const Constructors&... args)
963 {
964 _create(si, args...);
965 }
966
967 private:
968
969 // TODO: Create the 'FactoryInfo' instance in the constructor
970 InterfaceList m_interface_list;
971
972 private:
973
975 template <typename ConstructorType> void
976 _create(FactoryInfo& si, const ConstructorType&)
977 {
978 m_interface_list.template registerFactory<ConcreteType, ConstructorType>(si);
979 }
980
982 template <typename C1, typename C2, typename... OtherConstructors>
983 void _create(FactoryInfo& si, const C1& c1, const C2& c2, const OtherConstructors&... args)
984 {
985 _create<C1>(si, c1);
986 // Applies recursion on the remaining types
987 _create<C2, OtherConstructors...>(si, c2, args...);
988 }
989};
990
991/*---------------------------------------------------------------------------*/
992/*---------------------------------------------------------------------------*/
993
994} // namespace Arcane::DependencyInjection::impl
995
996/*---------------------------------------------------------------------------*/
997/*---------------------------------------------------------------------------*/
998
999#define ARCANE_DI_CONSTRUCTOR(...) \
1000 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<__VA_ARGS__>()
1001
1002#define ARCANE_DI_EMPTY_CONSTRUCTOR(...) \
1003 ::Arcane::DependencyInjection::impl::ConstructorRegisterer<>()
1004
1005// TODO: guarantee at least one interface
1006
1007#define ARCANE_DI_INTERFACES(...) \
1008 ::Arcane::DependencyInjection::impl::InterfaceListRegisterer<__VA_ARGS__>
1009
1010#define ARCANE_DI_REGISTER_PROVIDER(t_class, t_provider_property, t_interfaces, ...) \
1011 namespace \
1012 { \
1013 Arcane::DependencyInjection::impl::FactoryInfo \
1014 ARCCORE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class)(const Arcane::DependencyInjection::ProviderProperty& property) \
1015 { \
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__); \
1019 return si; \
1020 } \
1021 } \
1022 Arcane::DependencyInjection::impl::GlobalRegisterer ARCCORE_EXPORT ARCCORE_JOIN_WITH_LINE(globalServiceRegisterer##aclass)(&ARCCORE_JOIN_WITH_LINE(arcaneCreateDependencyInjectionProviderInfo##t_class), t_provider_property)
1023
1024/*---------------------------------------------------------------------------*/
1025/*---------------------------------------------------------------------------*/
1026
1027#endif
#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.
Ref< TrueType > createRef(Args &&... args)
Creates an instance of type TrueType with arguments Args and returns a reference to it.
Type
Type of JSON value.
Definition rapidjson.h:730