5
5
using System . Diagnostics . CodeAnalysis ;
6
6
using System . Reflection ;
7
7
using Microsoft . AspNetCore . Components . Reflection ;
8
- using Microsoft . Extensions . DependencyInjection ;
9
8
using static Microsoft . AspNetCore . Internal . LinkerFlags ;
10
9
11
10
namespace Microsoft . AspNetCore . Components ;
@@ -15,71 +14,46 @@ internal sealed class ComponentFactory
15
14
private const BindingFlags _injectablePropertyBindingFlags
16
15
= BindingFlags . Instance | BindingFlags . Public | BindingFlags . NonPublic ;
17
16
18
- private static readonly ConcurrentDictionary < Type , ComponentInitializer > _cachedInitializers = new ( ) ;
19
- private readonly IComponentActivator ? _componentActivator ;
17
+ private static readonly ConcurrentDictionary < Type , Action < IServiceProvider , IComponent > > _cachedInitializers = new ( ) ;
20
18
21
- public ComponentFactory ( IComponentActivator ? componentActivator )
19
+ private readonly IComponentActivator _componentActivator ;
20
+
21
+ public ComponentFactory ( IComponentActivator componentActivator )
22
22
{
23
- _componentActivator = componentActivator ;
23
+ _componentActivator = componentActivator ?? throw new ArgumentNullException ( nameof ( componentActivator ) ) ;
24
24
}
25
25
26
26
public static void ClearCache ( ) => _cachedInitializers . Clear ( ) ;
27
27
28
28
public IComponent InstantiateComponent ( IServiceProvider serviceProvider , [ DynamicallyAccessedMembers ( Component ) ] Type componentType )
29
29
{
30
- if ( _componentActivator is not null )
31
- {
32
- return InstantiateWithActivator ( _componentActivator , serviceProvider , componentType ) ;
33
- }
34
-
35
- return InstantiateDefault ( serviceProvider , componentType ) ;
36
- }
37
-
38
- private static IComponent InstantiateDefault ( IServiceProvider serviceProvider , [ DynamicallyAccessedMembers ( Component ) ] Type componentType )
39
- {
40
- // This is thread-safe because _cachedInitializers is a ConcurrentDictionary.
41
- // We might generate the initializer more than once for a given type, but would
42
- // still produce the correct result.
43
- if ( ! _cachedInitializers . TryGetValue ( componentType , out var initializer ) )
44
- {
45
- if ( ! typeof ( IComponent ) . IsAssignableFrom ( componentType ) )
46
- {
47
- throw new ArgumentException ( $ "The type { componentType . FullName } does not implement { nameof ( IComponent ) } .", nameof ( componentType ) ) ;
48
- }
49
-
50
- initializer = new ( CreatePropertyInitializer ( componentType ) , ActivatorUtilities . CreateFactory ( componentType , Type . EmptyTypes ) ) ;
51
- _cachedInitializers . TryAdd ( componentType , initializer ) ;
52
- }
53
-
54
- return initializer . CreateDefault ( serviceProvider ) ;
55
- }
56
-
57
- private static IComponent InstantiateWithActivator ( IComponentActivator componentActivator , IServiceProvider serviceProvider , [ DynamicallyAccessedMembers ( Component ) ] Type componentType )
58
- {
59
- var component = componentActivator . CreateInstance ( componentType ) ;
30
+ var component = _componentActivator . CreateInstance ( componentType ) ;
60
31
if ( component is null )
61
32
{
62
- // A user implemented IComponentActivator might return null.
33
+ // The default activator will never do this, but an externally-supplied one might
63
34
throw new InvalidOperationException ( $ "The component activator returned a null value for a component of type { componentType . FullName } .") ;
64
35
}
65
36
66
- // Use the activated type instead of specified type since the activator may return different/ derived instances.
67
- componentType = component . GetType ( ) ;
37
+ PerformPropertyInjection ( serviceProvider , component ) ;
38
+ return component ;
39
+ }
68
40
41
+ private static void PerformPropertyInjection ( IServiceProvider serviceProvider , IComponent instance )
42
+ {
69
43
// This is thread-safe because _cachedInitializers is a ConcurrentDictionary.
70
44
// We might generate the initializer more than once for a given type, but would
71
45
// still produce the correct result.
72
- if ( ! _cachedInitializers . TryGetValue ( componentType , out var initializer ) )
46
+ var instanceType = instance . GetType ( ) ;
47
+ if ( ! _cachedInitializers . TryGetValue ( instanceType , out var initializer ) )
73
48
{
74
- initializer = new ( CreatePropertyInitializer ( componentType ) ) ;
75
- _cachedInitializers . TryAdd ( componentType , initializer ) ;
49
+ initializer = CreateInitializer ( instanceType ) ;
50
+ _cachedInitializers . TryAdd ( instanceType , initializer ) ;
76
51
}
77
52
78
- initializer . ActivateProperties ( serviceProvider , component ) ;
79
- return component ;
53
+ initializer ( serviceProvider , instance ) ;
80
54
}
81
55
82
- private static Action < IServiceProvider , IComponent > CreatePropertyInitializer ( [ DynamicallyAccessedMembers ( Component ) ] Type type )
56
+ private static Action < IServiceProvider , IComponent > CreateInitializer ( [ DynamicallyAccessedMembers ( Component ) ] Type type )
83
57
{
84
58
// Do all the reflection up front
85
59
List < ( string name , Type propertyType , PropertySetter setter ) > ? injectables = null ;
@@ -119,29 +93,4 @@ void Initialize(IServiceProvider serviceProvider, IComponent component)
119
93
}
120
94
}
121
95
}
122
-
123
- private readonly struct ComponentInitializer
124
- {
125
- private readonly Action < IServiceProvider , IComponent > _propertyInitializer ;
126
-
127
- private readonly ObjectFactory ? _componentFactory ;
128
-
129
- public ComponentInitializer ( Action < IServiceProvider , IComponent > propertyInitializer , ObjectFactory ? componentFactory = null )
130
- {
131
- _propertyInitializer = propertyInitializer ;
132
- _componentFactory = componentFactory ;
133
- }
134
-
135
- public IComponent CreateDefault ( IServiceProvider serviceProvider )
136
- {
137
- var component = ( IComponent ) _componentFactory ! ( serviceProvider , Array . Empty < object ? > ( ) ) ;
138
- ActivateProperties ( serviceProvider , component ) ;
139
- return component ;
140
- }
141
-
142
- public void ActivateProperties ( IServiceProvider serviceProvider , IComponent component )
143
- {
144
- _propertyInitializer ( serviceProvider , component ) ;
145
- }
146
- }
147
96
}
0 commit comments