@@ -14,68 +14,130 @@ internal static class TypeLoader
1414{
1515 private static readonly ConcurrentDictionary < string , Type > Assemblies = new ( ) ;
1616 private static readonly ConcurrentDictionary < Type , object > Instances = new ( ) ;
17+ private static readonly ConcurrentBag < ( string FullName , Type Type ) > InstancesWhichCannotBeFoundByFullName = [ ] ;
18+ private static readonly ConcurrentBag < ( string FullName , Type Type ) > StaticInstancesWhichCannotBeFoundByFullName = [ ] ;
19+ private static readonly ConcurrentBag < Type > InstancesWhichCannotBeFound = [ ] ;
20+ private static readonly ConcurrentBag < Type > StaticInstancesWhichCannotBeFound = [ ] ;
1721
18- public static TInterface LoadNewInstance < TInterface > ( params object ? [ ] args ) where TInterface : class
22+ public static bool TryLoadNewInstance < TInterface > ( [ NotNullWhen ( true ) ] out TInterface ? instance , params object ? [ ] args ) where TInterface : class
1923 {
20- var pluginType = GetPluginType < TInterface > ( ) ;
24+ var type = typeof ( TInterface ) ;
25+ if ( InstancesWhichCannotBeFound . Contains ( type ) )
26+ {
27+ instance = null ;
28+ return false ;
29+ }
30+
31+ if ( TryGetPluginType < TInterface > ( out var pluginType ) )
32+ {
33+ instance = ( TInterface ) Activator . CreateInstance ( pluginType , args ) ! ;
34+ return true ;
35+ }
2136
22- return ( TInterface ) Activator . CreateInstance ( pluginType , args ) ! ;
37+ InstancesWhichCannotBeFound . Add ( type ) ;
38+ instance = null ;
39+ return false ;
2340 }
2441
25- public static TInterface LoadStaticInstance < TInterface > ( params object ? [ ] args ) where TInterface : class
42+ public static bool TryLoadStaticInstance < TInterface > ( [ NotNullWhen ( true ) ] out TInterface ? staticInstance , params object ? [ ] args ) where TInterface : class
2643 {
27- var pluginType = GetPluginType < TInterface > ( ) ;
44+ var type = typeof ( TInterface ) ;
45+ if ( StaticInstancesWhichCannotBeFound . Contains ( type ) )
46+ {
47+ staticInstance = null ;
48+ return false ;
49+ }
2850
29- return ( TInterface ) Instances . GetOrAdd ( pluginType , key => Activator . CreateInstance ( key , args ) ! ) ;
51+ if ( TryGetPluginType < TInterface > ( out var pluginType ) )
52+ {
53+ staticInstance = ( TInterface ) Instances . GetOrAdd ( pluginType , key => Activator . CreateInstance ( key , args ) ! ) ;
54+ return true ;
55+ }
56+
57+ StaticInstancesWhichCannotBeFound . Add ( type ) ;
58+ staticInstance = null ;
59+ return false ;
3060 }
3161
32- public static TInterface LoadNewInstanceByFullName < TInterface > ( string implementationTypeFullName , params object ? [ ] args ) where TInterface : class
62+ public static bool TryLoadNewInstanceByFullName < TInterface > ( [ NotNullWhen ( true ) ] out TInterface ? instance , string implementationTypeFullName , params object ? [ ] args ) where TInterface : class
3363 {
3464 Guard . NotNullOrEmpty ( implementationTypeFullName ) ;
3565
36- var pluginType = GetPluginTypeByFullName < TInterface > ( implementationTypeFullName ) ;
66+ var type = typeof ( TInterface ) ;
67+ if ( InstancesWhichCannotBeFoundByFullName . Contains ( ( implementationTypeFullName , type ) ) )
68+ {
69+ instance = null ;
70+ return false ;
71+ }
72+
73+ if ( TryGetPluginTypeByFullName < TInterface > ( implementationTypeFullName , out var pluginType ) )
74+ {
75+ instance = ( TInterface ) Activator . CreateInstance ( pluginType , args ) ! ;
76+ return true ;
77+ }
3778
38- return ( TInterface ) Activator . CreateInstance ( pluginType , args ) ! ;
79+ InstancesWhichCannotBeFoundByFullName . Add ( ( implementationTypeFullName , type ) ) ;
80+ instance = null ;
81+ return false ;
3982 }
4083
41- public static TInterface LoadStaticInstanceByFullName < TInterface > ( string implementationTypeFullName , params object ? [ ] args ) where TInterface : class
84+ public static bool TryLoadStaticInstanceByFullName < TInterface > ( [ NotNullWhen ( true ) ] out TInterface ? staticInstance , string implementationTypeFullName , params object ? [ ] args ) where TInterface : class
4285 {
4386 Guard . NotNullOrEmpty ( implementationTypeFullName ) ;
4487
45- var pluginType = GetPluginTypeByFullName < TInterface > ( implementationTypeFullName ) ;
88+ var type = typeof ( TInterface ) ;
89+ if ( StaticInstancesWhichCannotBeFoundByFullName . Contains ( ( implementationTypeFullName , type ) ) )
90+ {
91+ staticInstance = null ;
92+ return false ;
93+ }
94+
95+ if ( TryGetPluginTypeByFullName < TInterface > ( implementationTypeFullName , out var pluginType ) )
96+ {
97+ staticInstance = ( TInterface ) Instances . GetOrAdd ( pluginType , key => Activator . CreateInstance ( key , args ) ! ) ;
98+ return true ;
99+ }
46100
47- return ( TInterface ) Instances . GetOrAdd ( pluginType , key => Activator . CreateInstance ( key , args ) ! ) ;
101+ StaticInstancesWhichCannotBeFoundByFullName . Add ( ( implementationTypeFullName , type ) ) ;
102+ staticInstance = null ;
103+ return false ;
48104 }
49105
50- private static Type GetPluginType < TInterface > ( ) where TInterface : class
106+ private static bool TryGetPluginType < TInterface > ( [ NotNullWhen ( true ) ] out Type ? foundType ) where TInterface : class
51107 {
52108 var key = typeof ( TInterface ) . FullName ! ;
53109
54- return Assemblies . GetOrAdd ( key , _ =>
110+ if ( Assemblies . TryGetValue ( key , out foundType ) )
55111 {
56- if ( TryFindTypeInDlls < TInterface > ( null , out var foundType ) )
57- {
58- return foundType ;
59- }
112+ return true ;
113+ }
60114
61- throw new DllNotFoundException ( $ "No dll found which implements interface '{ key } '.") ;
62- } ) ;
115+ if ( TryFindTypeInDlls < TInterface > ( null , out foundType ) )
116+ {
117+ Assemblies . TryAdd ( key , foundType ) ;
118+ return true ;
119+ }
120+
121+ return false ;
63122 }
64123
65- private static Type GetPluginTypeByFullName < TInterface > ( string implementationTypeFullName ) where TInterface : class
124+ private static bool TryGetPluginTypeByFullName < TInterface > ( string implementationTypeFullName , [ NotNullWhen ( true ) ] out Type ? foundType ) where TInterface : class
66125 {
67126 var @interface = typeof ( TInterface ) . FullName ;
68127 var key = $ "{ @interface } _{ implementationTypeFullName } ";
69128
70- return Assemblies . GetOrAdd ( key , _ =>
129+ if ( Assemblies . TryGetValue ( key , out foundType ) )
71130 {
72- if ( TryFindTypeInDlls < TInterface > ( implementationTypeFullName , out var foundType ) )
73- {
74- return foundType ;
75- }
131+ return true ;
132+ }
76133
77- throw new DllNotFoundException ( $ "No dll found which implements Interface '{ @interface } ' and has FullName '{ implementationTypeFullName } '.") ;
78- } ) ;
134+ if ( TryFindTypeInDlls < TInterface > ( implementationTypeFullName , out foundType ) )
135+ {
136+ Assemblies . TryAdd ( key , foundType ) ;
137+ return true ;
138+ }
139+
140+ return false ;
79141 }
80142
81143 private static bool TryFindTypeInDlls < TInterface > ( string ? implementationTypeFullName , [ NotNullWhen ( true ) ] out Type ? pluginType ) where TInterface : class
0 commit comments