1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Linq ;
4
+ using System . Reflection ;
3
5
using Autofac ;
4
6
using Autofac . Builder ;
5
7
using Autofac . Core ;
6
- using Autofac . Features . OpenGenerics ;
8
+ using Autofac . Core . Activators . Delegate ;
7
9
8
10
namespace LazyProxy . Autofac
9
11
{
@@ -12,8 +14,27 @@ namespace LazyProxy.Autofac
12
14
/// </summary>
13
15
public static class AutofacExtensions
14
16
{
17
+ private static readonly ConstructorInfo RegistrationBuilderConstructor ;
18
+
19
+ static AutofacExtensions ( )
20
+ {
21
+ // There is no way to create RegistrationBuilder with TypedService / KeyedService without reflection.
22
+ RegistrationBuilderConstructor = typeof ( ILifetimeScope ) . Assembly
23
+ . GetType ( "Autofac.Builder.RegistrationBuilder`3" )
24
+ . MakeGenericType (
25
+ typeof ( object ) ,
26
+ typeof ( SimpleActivatorData ) ,
27
+ typeof ( SingleRegistrationStyle ) )
28
+ . GetConstructor ( new [ ]
29
+ {
30
+ typeof ( Service ) ,
31
+ typeof ( SimpleActivatorData ) ,
32
+ typeof ( SingleRegistrationStyle )
33
+ } ) ;
34
+ }
35
+
15
36
/// <summary>
16
- /// Is used to register non open generic interface TFrom to class TTo by creation a lazy proxy at runtime.
37
+ /// Is used to register interface TFrom to class TTo by creation a lazy proxy at runtime.
17
38
/// The real class To will be instantiated only after first method or property execution.
18
39
/// </summary>
19
40
/// <param name="builder">The instance of the Autofac container builder.</param>
@@ -29,7 +50,7 @@ public static IRegistrationBuilder<object, SimpleActivatorData, SingleRegistrati
29
50
builder . RegisterLazy ( typeof ( TFrom ) , typeof ( TTo ) , name , nonLazyRegistrationMutator ) ;
30
51
31
52
/// <summary>
32
- /// Is used to register non open generic interface TFrom to class TTo by creation a lazy proxy at runtime.
53
+ /// Is used to register interface TFrom to class TTo by creation a lazy proxy at runtime.
33
54
/// The real class To will be instantiated only after first method or property execution.
34
55
/// </summary>
35
56
/// <param name="typeFrom">The linked interface.</param>
@@ -45,68 +66,73 @@ public static IRegistrationBuilder<object, SimpleActivatorData, SingleRegistrati
45
66
// There is no way to constraint it on the compilation step.
46
67
if ( ! typeFrom . IsInterface )
47
68
{
48
- throw new NotSupportedException (
49
- "The lazy registration is supported only for interfaces." ) ;
69
+ throw new NotSupportedException ( "The lazy registration is supported only for interfaces." ) ;
50
70
}
51
71
72
+ var registrationName = Guid . NewGuid ( ) . ToString ( ) ;
73
+ IRegistrationBuilder < object , SimpleActivatorData , SingleRegistrationStyle > registration ;
74
+
52
75
if ( typeTo . IsGenericTypeDefinition )
53
76
{
54
- throw new ArgumentException (
55
- $ "{ typeFrom } is an open generic type definition. Use the 'RegisterGenericLazy' method instead.") ;
56
- }
77
+ var nonLazyRegistration = builder . RegisterGeneric ( typeTo ) . Named ( registrationName , typeFrom ) ;
78
+ nonLazyRegistrationMutator ? . Mutate ( nonLazyRegistration ) ;
57
79
58
- var registrationName = Guid . NewGuid ( ) . ToString ( ) ;
59
- var nonLazyRegistration = builder . RegisterType ( typeTo ) . Named ( registrationName , typeFrom ) ;
60
- nonLazyRegistrationMutator ? . Mutate ( nonLazyRegistration ) ;
80
+ registration = builder . RegisterGenericFactory ( typeFrom , name ,
81
+ ( c , t , n , p ) => CreateLazyProxy ( c , t , registrationName , p ) ) ;
82
+ }
83
+ else
84
+ {
85
+ var nonLazyRegistration = builder . RegisterType ( typeTo ) . Named ( registrationName , typeFrom ) ;
86
+ nonLazyRegistrationMutator ? . Mutate ( nonLazyRegistration ) ;
61
87
62
- var registration = builder . Register ( ( c , p ) =>
63
- CreateLazyProxy ( c . Resolve < IComponentContext > ( ) , typeFrom , registrationName , p ) ) ;
88
+ registration = builder . Register (
89
+ ( c , p ) => CreateLazyProxy ( c . Resolve < IComponentContext > ( ) , typeFrom , registrationName , p ) ) ;
90
+ }
64
91
65
92
return name == null
66
93
? registration . As ( typeFrom )
67
94
: registration . Named ( name , typeFrom ) ;
68
95
}
69
96
70
97
/// <summary>
71
- /// Is used to register open generic interface TFrom to class TTo by creation a lazy proxy at runtime.
72
- /// The real class To will be instantiated only after first method or property execution.
98
+ /// Registers a delegate as a component for open generic types.
73
99
/// </summary>
74
- /// <param name="typeFrom">The linked interface.</param>
75
- /// <param name="typeTo">The linked class.</param>
76
100
/// <param name="builder">The instance of the Autofac container builder.</param>
77
- /// <param name="name">The registration name. Null if named registration is not required.</param>
78
- /// <param name="nonLazyRegistrationMutator">A mutator allowing to change the non-lazy registration.</param>
79
- /// <returns>The instance of the Autofac registration builder.</returns>
80
- public static IRegistrationBuilder < object , OpenGenericDelegateActivatorData , DynamicRegistrationStyle >
81
- RegisterGenericLazy ( this ContainerBuilder builder , Type typeFrom , Type typeTo , string name = null ,
82
- IRegistrationMutator nonLazyRegistrationMutator = null )
101
+ /// <param name="type"><see cref="Type"/> of the registered component.</param>
102
+ /// <param name="name">Name of the registered component.</param>
103
+ /// <param name="factory">The delegate to register.</param>
104
+ /// <returns>Registration builder allowing the registration to be configured.</returns>
105
+ public static IRegistrationBuilder < object , SimpleActivatorData , SingleRegistrationStyle >
106
+ RegisterGenericFactory ( this ContainerBuilder builder , Type type , string name ,
107
+ Func < IComponentContext , Type , string , Parameter [ ] , object > factory )
83
108
{
84
- // There is no way to constraint it on the compilation step.
85
- if ( ! typeFrom . IsInterface )
86
- {
87
- throw new NotSupportedException (
88
- "The lazy registration is supported only for interfaces." ) ;
89
- }
109
+ var registration = ( IRegistrationBuilder < object , SimpleActivatorData , SingleRegistrationStyle > )
110
+ RegistrationBuilderConstructor . Invoke ( new [ ]
111
+ {
112
+ string . IsNullOrEmpty ( name )
113
+ ? ( object ) new TypedService ( type )
114
+ : new KeyedService ( name , type ) ,
90
115
91
- if ( ! typeTo . IsGenericTypeDefinition )
92
- {
93
- throw new ArgumentException (
94
- $ "{ typeFrom } is not an open generic type definition. Use the 'RegisterLazy' method instead.") ;
95
- }
116
+ new SimpleActivatorData ( new DelegateActivator ( type ,
117
+ ( c , p ) =>
118
+ {
119
+ var parameters = p . ToArray ( ) ;
120
+ var serviceType = parameters . Named < Type > ( OpenGenericFactoryRegistrationSource . ServiceType ) ;
121
+ var context = c . Resolve < IComponentContext > ( ) ;
96
122
97
- var registrationName = Guid . NewGuid ( ) . ToString ( ) ;
98
- var nonLazyRegistration = builder . RegisterGeneric ( typeTo ) . Named ( registrationName , typeFrom ) ;
99
- nonLazyRegistrationMutator ? . Mutate ( nonLazyRegistration ) ;
123
+ return factory ( context , serviceType , name , parameters ) ;
124
+ } ) ) ,
100
125
101
- var registration = builder . RegisterGeneric ( ( c , t , p ) =>
102
- {
103
- var closedTypeFrom = typeFrom . MakeGenericType ( t ) ;
104
- return CreateLazyProxy ( c . Resolve < IComponentContext > ( ) , closedTypeFrom , registrationName , p ) ;
105
- } ) ;
126
+ new SingleRegistrationStyle ( )
127
+ } ) ;
106
128
107
- return name == null
108
- ? registration . As ( typeFrom )
109
- : registration . Named ( name , typeFrom ) ;
129
+ registration . RegistrationData . DeferredCallback = builder . RegisterCallback (
130
+ cr => cr . AddRegistrationSource (
131
+ new OpenGenericFactoryRegistrationSource (
132
+ registration . RegistrationData ,
133
+ registration . ActivatorData ) ) ) ;
134
+
135
+ return registration ;
110
136
}
111
137
112
138
private static object CreateLazyProxy (
0 commit comments