• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Sholtee / injector / 2270

06 Dec 2024 06:22AM UTC coverage: 91.153% (+0.4%) from 90.719%
2270

push

appveyor

Sholtee
seems net5.0 is not supported by AppVeyor anymore

1937 of 2125 relevant lines covered (91.15%)

4.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.1
/SRC/Interfaces/Public/Extensions/IServiceCollectionBasicExtensions/Factory.cs
1
/********************************************************************************
2
* Factory.cs                                                                    *
3
*                                                                               *
4
* Author: Denes Solti                                                           *
5
********************************************************************************/
6
using System;
7
using System.Linq.Expressions;
8
using System.Runtime.CompilerServices;
9

10
namespace Solti.Utils.DI.Interfaces
11
{
12
    public static partial class IServiceCollectionBasicExtensions
13
    {
14
        /// <summary>
15
        /// Registers a new service factory with the given type. Factories are also services except that the instantiating process is delegated to the caller. Useful if a service has more than one constructor:
16
        /// <code>
17
        /// ScopeFactory.Create
18
        /// (
19
        ///     svcs => svcs.Factory(typeof(IMyService), "serviceName", (scope, type) => new MyService(...), Lifetime.Singleton),
20
        ///     ...
21
        /// )
22
        /// </code>
23
        /// </summary>
24
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
25
        /// <param name="type">The service type to be registered. It can not be null and can be registered only once (with the given <paramref name="key"/>).</param>
26
        /// <param name="key">The (optional) service key (usually a name).</param>
27
        /// <param name="factoryExpr">The factory function that is responsible for the instantiation. Its call count depends on the value of the <paramref name="lifetime"/> parameter. Note that the second parameter of the <paramref name="factoryExpr"/> is never generic, even if you registered the factory for an open generic interface.</param>
28
        /// <param name="lifetime">The lifetime of service.</param>
29
        /// <param name="options">Options to be assigned to the service being registered.</param>
30
        /// <remarks>You can register generic services (where the <paramref name="type"/> parameter is an open generic type).</remarks>
31
        [OverloadResolutionPriority(1)]
32
        public static IServiceCollection Factory(this IServiceCollection self, Type type, object? key, Expression<FactoryDelegate> factoryExpr, LifetimeBase lifetime, ServiceOptions? options = null)
33
        {
5✔
34
            if (self is null)
5✔
35
                throw new ArgumentNullException(nameof(self));
5✔
36

37
            if (type is null)
5✔
38
                throw new ArgumentNullException(nameof(type));
5✔
39

40
            if (factoryExpr is null)
5✔
41
                throw new ArgumentNullException(nameof(factoryExpr));
5✔
42

43
            if (lifetime is null)
5✔
44
                throw new ArgumentNullException(nameof(lifetime));
5✔
45

46
            return self.Register
5✔
47
            (
5✔
48
                //
5✔
49
                // Further validations are done by the created xXxServiceEntry
5✔
50
                //
5✔
51

5✔
52
                lifetime.CreateFrom(type, key, factoryExpr, options ?? ServiceOptions.Default)
5✔
53
            );
5✔
54
        }
5✔
55

56
        /// <summary>
57
        /// Registers a new service factory with the given type. Factories are also services except that the instantiating process is delegated to the caller. Useful if a service has more than one constructor:
58
        /// <code>
59
        /// ScopeFactory.Create
60
        /// (
61
        ///     svcs => svcs.Factory(typeof(IMyService), "serviceName", (scope, type) => new MyService(...), Lifetime.Singleton),
62
        ///     ...
63
        /// )
64
        /// </code>
65
        /// </summary>
66
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
67
        /// <param name="type">The service type to be registered. It can not be null and can be registered only once (with the given <paramref name="key"/>).</param>
68
        /// <param name="key">The (optional) service key (usually a name).</param>
69
        /// <param name="factory">The factory function that is responsible for the instantiation. Its call count depends on the value of the <paramref name="lifetime"/> parameter. Note that the second parameter of the <paramref name="factory"/> is never generic, even if you registered the factory for an open generic interface.</param>
70
        /// <param name="lifetime">The lifetime of service.</param>
71
        /// <param name="options">Options to be assigned to the service being registered.</param>
72
        /// <remarks>
73
        /// <list type="bullet">
74
        /// <item>You can register generic services (where the <paramref name="type"/> parameter is an open generic type).</item>
75
        /// <item>It's advised to utilize <paramref name="factory"/> expressions (using the <see cref="Factory(IServiceCollection, Type, object?, Expression{FactoryDelegate}, LifetimeBase, ServiceOptions?)"/> method) insted of real factories as they are more performant.</item>
76
        /// </list>
77
        /// </remarks>
78
        public static IServiceCollection Factory(this IServiceCollection self, Type type, object? key, FactoryDelegate factory, LifetimeBase lifetime, ServiceOptions? options = null)
79
            => factory is not null
5✔
80
                ? self.Factory(type, key, (scope, type) => factory(scope, type), lifetime, options)
5✔
81
                : throw new ArgumentNullException(nameof(factory));
5✔
82

83
        /// <summary>
84
        /// Registers a new service factory with the given type. Factories are also services except that the instantiating process is delegated to the caller. Useful if a service has more than one constructor:
85
        /// <code>
86
        /// ScopeFactory.Create
87
        /// (
88
        ///     svcs => svcs.Factory(typeof(IMyService), (scope, type) => new MyService(...), Lifetime.Singleton),
89
        ///     ...
90
        /// )
91
        /// </code>
92
        /// </summary>
93
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
94
        /// <param name="type">The service type to be registered. It can not be null and can be registered only once.</param>
95
        /// <param name="factoryExpr">The factory function that is responsible for the instantiation. Its call count depends on the value of the <paramref name="lifetime"/> parameter. Note that the second parameter of the <paramref name="factoryExpr"/> is never generic, even if you registered the factory for an open generic interface.</param>
96
        /// <param name="lifetime">The lifetime of service.</param>
97
        /// <param name="options">Options to be assigned to the service being registered.</param>
98
        /// <remarks>You can register generic services (where the <paramref name="type"/> parameter is an open generic type).</remarks>
99
        [OverloadResolutionPriority(1)]
100
        public static IServiceCollection Factory(this IServiceCollection self, Type type, Expression<FactoryDelegate> factoryExpr, LifetimeBase lifetime, ServiceOptions? options = null) 
101
            => self.Factory(type, null, factoryExpr, lifetime, options);
5✔
102

103
        /// <summary>
104
        /// Registers a new service factory with the given type. Factories are also services except that the instantiating process is delegated to the caller. Useful if a service has more than one constructor:
105
        /// <code>
106
        /// ScopeFactory.Create
107
        /// (
108
        ///     svcs => svcs.Factory(typeof(IMyService), (scope, type) => new MyService(...), Lifetime.Singleton),
109
        ///     ...
110
        /// )
111
        /// </code>
112
        /// </summary>
113
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
114
        /// <param name="type">The service type to be registered. It can not be null and can be registered only once.</param>
115
        /// <param name="factory">The factory function that is responsible for the instantiation. Its call count depends on the value of the <paramref name="lifetime"/> parameter. Note that the second parameter of the <paramref name="factory"/> is never generic, even if you registered the factory for an open generic interface.</param>
116
        /// <param name="lifetime">The lifetime of service.</param>
117
        /// <param name="options">Options to be assigned to the service being registered.</param>
118
        /// <remarks>
119
        /// <list type="bullet">
120
        /// <item>You can register generic services (where the <paramref name="type"/> parameter is an open generic type).</item>
121
        /// <item>It's advised to utilize <paramref name="factory"/> expressions (using the <see cref="Factory(IServiceCollection, Type, Expression{FactoryDelegate}, LifetimeBase, ServiceOptions?)"/> method) insted of real factories as they are more performant.</item>
122
        /// </list>
123
        /// </remarks>
124
        public static IServiceCollection Factory(this IServiceCollection self, Type type, FactoryDelegate factory, LifetimeBase lifetime, ServiceOptions? options = null)
125
            => self.Factory(type, null, factory, lifetime, options);
5✔
126

127
        /// <summary>
128
        /// Registers a new service factory with the given type. Factories are also services except that the instantiating process is delegated to the caller. Useful if a service has more than one constructor:
129
        /// <code>
130
        /// ScopeFactory.Create
131
        /// (
132
        ///     svcs => svcs.Factory&lt;IMyService&gt;("serviceName", scope => new MyService(...), Lifetime.Singleton),
133
        ///     ...
134
        /// )
135
        /// </code>
136
        /// </summary>
137
        /// <typeparam name="TType">The service type to be registered. It can be registered only once (with the given <paramref name="key"/>).</typeparam>
138
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
139
        /// <param name="key">The (optional) service key (usually a name).</param>
140
        /// <param name="factoryExpr">The factory function that is responsible for the instantiation. Its call count depends on the value of the <paramref name="lifetime"/> parameter.</param>
141
        /// <param name="lifetime">The lifetime of service.</param>
142
        /// <param name="options">Options to be assigned to the service being registered.</param>
143
        [OverloadResolutionPriority(1)]
144
        public static IServiceCollection Factory<TType>(this IServiceCollection self, object? key, Expression<FactoryDelegate<TType>> factoryExpr, LifetimeBase lifetime, ServiceOptions? options = null) where TType : class
145
            => self.Factory(typeof(TType), key, WrapToStandardDelegate(factoryExpr), lifetime, options);
5✔
146

147
        /// <summary>
148
        /// Registers a new service factory with the given type. Factories are also services except that the instantiating process is delegated to the caller. Useful if a service has more than one constructor:
149
        /// <code>
150
        /// ScopeFactory.Create
151
        /// (
152
        ///     svcs => svcs.Factory&lt;IMyService&gt;("serviceName", scope => new MyService(...), Lifetime.Singleton),
153
        ///     ...
154
        /// )
155
        /// </code>
156
        /// </summary>
157
        /// <typeparam name="TType">The service type to be registered. It can be registered only once (with the given <paramref name="key"/>).</typeparam>
158
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
159
        /// <param name="key">The (optional) service key (usually a name).</param>
160
        /// <param name="factory">The factory function that is responsible for the instantiation. Its call count depends on the value of the <paramref name="lifetime"/> parameter.</param>
161
        /// <param name="lifetime">The lifetime of service.</param>
162
        /// <param name="options">Options to be assigned to the service being registered.</param>
163
        /// <remarks>
164
        /// <list type="bullet">
165
        /// <item>You can register generic services (where the <typeparamref name="TType"/> is an open generic type).</item>
166
        /// <item>It's advised to utilize <paramref name="factory"/> expressions (using the <see cref="Factory{TType}(IServiceCollection, object?, Expression{FactoryDelegate{TType}}, LifetimeBase, ServiceOptions?)"/> method) insted of real factories as they are more performant.</item>
167
        /// </list>
168
        /// </remarks>
169
        public static IServiceCollection Factory<TType>(this IServiceCollection self, object? key, FactoryDelegate<TType> factory, LifetimeBase lifetime, ServiceOptions? options = null) where TType : class
170
            => factory is not null
×
171
                ? self.Factory(key, scope => factory(scope), lifetime, options)
×
172
                : throw new ArgumentNullException(nameof(factory));
×
173

174
        /// <summary>
175
        /// Registers a new service factory with the given type. Factories are also services except that the instantiating process is delegated to the caller. Useful if a service has more than one constructor:
176
        /// <code>
177
        /// ScopeFactory.Create
178
        /// (
179
        ///     svcs => svcs.Factory&lt;IMyService&gt;(scope => new MyService(...), Lifetime.Singleton),
180
        ///     ...
181
        /// )
182
        /// </code>
183
        /// </summary>
184
        /// <typeparam name="TType">The service type to be registered. It can be registered only once.</typeparam>
185
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
186
        /// <param name="factoryExpr">The factory function that is responsible for the instantiation. Its call count depends on the value of the <paramref name="lifetime"/> parameter.</param>
187
        /// <param name="lifetime">The lifetime of service.</param>
188
        /// <param name="options">Options to be assigned to the service being registered.</param>
189
        [OverloadResolutionPriority(1)]
190
        public static IServiceCollection Factory<TType>(this IServiceCollection self, Expression<FactoryDelegate<TType>> factoryExpr, LifetimeBase lifetime, ServiceOptions? options = null) where TType : class
191
            => self.Factory(typeof(TType), null, WrapToStandardDelegate(factoryExpr), lifetime, options);
5✔
192

193
        /// <summary>
194
        /// Registers a new service factory with the given type. Factories are also services except that the instantiating process is delegated to the caller. Useful if a service has more than one constructor:
195
        /// <code>
196
        /// ScopeFactory.Create
197
        /// (
198
        ///     svcs => svcs.Factory&lt;IMyService&gt;(scope => new MyService(...), Lifetime.Singleton),
199
        ///     ...
200
        /// )
201
        /// </code>
202
        /// </summary>
203
        /// <typeparam name="TType">The service type to be registered. It can be registered only once.</typeparam>
204
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
205
        /// <param name="factory">The factory function that is responsible for the instantiation. Its call count depends on the value of the <paramref name="lifetime"/> parameter.</param>
206
        /// <param name="lifetime">The lifetime of service.</param>
207
        /// <param name="options">Options to be assigned to the service being registered.</param>
208
        /// <remarks>
209
        /// <list type="bullet">
210
        /// <item>You can register generic services (where the <typeparamref name="TType"/> is an open generic type).</item>
211
        /// <item>It's advised to utilize <paramref name="factory"/> expressions (using the <see cref="Factory{TType}(IServiceCollection, Expression{FactoryDelegate{TType}}, LifetimeBase, ServiceOptions?)"/> method) insted of real factories as they are more performant.</item>
212
        /// </list>
213
        /// </remarks>
214
        public static IServiceCollection Factory<TType>(this IServiceCollection self, FactoryDelegate<TType> factory, LifetimeBase lifetime, ServiceOptions? options = null) where TType : class
215
            => self.Factory(null, factory, lifetime, options);
×
216

217
        private static Expression<FactoryDelegate> WrapToStandardDelegate<TInterface>(Expression<FactoryDelegate<TInterface>> factoryExpr) where TInterface : class
218
        {
5✔
219
            if (factoryExpr is null)
5✔
220
                throw new ArgumentNullException(nameof(factoryExpr));
×
221

222
            ParameterExpression
5✔
223
                injector = factoryExpr.Parameters[0],
5✔
224
                type = Expression.Parameter(typeof(Type), nameof(type));
5✔
225

226
            return Expression.Lambda<FactoryDelegate>
5✔
227
            (
5✔
228
                factoryExpr.Body,
5✔
229
                injector,
5✔
230
                type
5✔
231
            );
5✔
232
        }
5✔
233
    }
234
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc