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

Sholtee / injector / 2208

29 Sep 2023 02:45PM UTC coverage: 93.661% (-0.3%) from 93.921%
2208

push

appveyor

Sholtee
introduce non-string service name support

1374 of 1467 relevant lines covered (93.66%)

2.81 hits per line

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

90.24
/SRC/Interfaces/Public/Extensions/IServiceCollectionBasicExtensions/Provider.cs
1
/********************************************************************************
2
* Provider.cs                                                                   *
3
*                                                                               *
4
* Author: Denes Solti                                                           *
5
********************************************************************************/
6
using System;
7
using System.Linq;
8
using System.Reflection;
9

10
namespace Solti.Utils.DI.Interfaces
11
{
12
    using Properties;
13

14
    public static partial class IServiceCollectionBasicExtensions
15
    {
16
        /// <summary>
17
        /// Registers a new service provider having non-interface dependency. Providers are "factory services" responsible for creating the concrete service:
18
        /// <code>
19
        /// class MyServiceProvider: IServiceProvider
20
        /// {
21
        ///     public int Depdendency { get; init; }
22
        ///     public object GetService(Type iface) => ...;
23
        /// }
24
        /// ...
25
        /// ScopeFactory.Create
26
        /// (
27
        ///     svcs => svcs.Provider(typeof(IMyService), "serviceName", typeof(MyServiceProvider), new { Depdendency = 1986 }, Lifetime.Singleton),
28
        ///     ...
29
        /// )
30
        /// </code>
31
        /// </summary>
32
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
33
        /// <param name="iface">The interface of the service. It will be forwarded to the provider.</param>
34
        /// <param name="name">The (optional) name of the service.</param>
35
        /// <param name="provider">The type of the provider. It may have dependencies and must implement the <see cref="IServiceProvider"/> interface.</param>
36
        /// <param name="explicitArgs">Explicit arguments, provided by the user.</param>
37
        /// <param name="lifetime">The lifetime of service.</param>
38
        /// <param name="options">Options to be assigned to the service being registered.</param>
39
        /// <remarks>The provided <see cref="IServiceProvider"/> implementation won't be disposed even if it implements the <see cref="IDisposable"/> interface.</remarks>
40
        public static IServiceCollection Provider(this IServiceCollection self, Type iface, object? name, Type provider, object explicitArgs, LifetimeBase lifetime, ServiceOptions? options = null)
41
        {
3✔
42
            if (self is null)
3✔
43
                throw new ArgumentNullException(nameof(self));
×
44

45
            if (iface is null)
3✔
46
                throw new ArgumentNullException(nameof(iface));
3✔
47

48
            if (provider is null)
3✔
49
                throw new ArgumentNullException(nameof(provider));
3✔
50

51
            if (explicitArgs is null)
3✔
52
                throw new ArgumentNullException(nameof(explicitArgs));
3✔
53

54
            if (lifetime is null)
3✔
55
                throw new ArgumentNullException(nameof(lifetime));
3✔
56

57
            //
58
            // Further validations are done by the created xXxServiceEntry
59
            //
60

61
            if (!typeof(IServiceProvider).IsAssignableFrom(provider))
3✔
62
                throw new ArgumentException(string.Format(Resources.Culture, Resources.NOT_IMPLEMENTED, typeof(IServiceProvider)), nameof(provider));
3✔
63

64
            if (iface.IsGenericTypeDefinition)
3✔
65
                throw new NotSupportedException(Resources.OPEN_GENERIC);
×
66

67
            //
68
            // Provider cannot have aspects (as it doesn't implement the service interface directly).
69
            //
70

71
            if (provider.GetCustomAttributes<AspectAttribute>(inherit: true).Any())
3✔
72
                throw new NotSupportedException(Resources.DECORATING_NOT_SUPPORTED);
×
73

74
            return self
3✔
75
                .Service(iface, name, provider, explicitArgs, lifetime, options)
76
                .Decorate(static (injector, iface, instance) => ((IServiceProvider) instance).GetService(iface));
77
        }
3✔
78

79
        /// <summary>
80
        /// Registers a new service provider. Providers are "factory services" responsible for creating the concrete service.
81
        /// <code>
82
        /// class MyServiceProvider: IServiceProvider
83
        /// {
84
        ///     [Inject]
85
        ///     public IDependency Depdendency { get; init; }
86
        ///     public object GetService(Type iface) => ...;
87
        /// }
88
        /// ...
89
        /// ScopeFactory.Create
90
        /// (
91
        ///     svcs => svcs.Provider(typeof(IMyService), "serviceName", typeof(MyServiceProvider), Lifetime.Singleton),
92
        ///     ...
93
        /// )
94
        /// </code>
95
        /// </summary>
96
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
97
        /// <param name="iface">The interface of the service. It will be forwarded to the provider.</param>
98
        /// <param name="name">The (optional) name of the service.</param>
99
        /// <param name="provider">The type of the provider. It may have dependencies and must implement the <see cref="IServiceProvider"/> interface.</param>
100
        /// <param name="lifetime">The lifetime of service.</param>
101
        /// <param name="options">Options to be assigned to the service being registered.</param>
102
        /// <remarks>The provided <see cref="IServiceProvider"/> implementation won't be disposed even if it implements the <see cref="IDisposable"/> interface.</remarks>
103
        public static IServiceCollection Provider(this IServiceCollection self, Type iface, object? name, Type provider, LifetimeBase lifetime, ServiceOptions? options = null)
104
        {
3✔
105
            if (self is null)
3✔
106
                throw new ArgumentNullException(nameof(self));
×
107

108
            if (iface is null)
3✔
109
                throw new ArgumentNullException(nameof(iface));
3✔
110

111
            if (provider is null)
3✔
112
                throw new ArgumentNullException(nameof(provider));
3✔
113

114
            if (lifetime is null)
3✔
115
                throw new ArgumentNullException(nameof(lifetime));
3✔
116

117
            //
118
            // Further validations are done by the created xXxServiceEntry
119
            //
120

121
            if (!typeof(IServiceProvider).IsAssignableFrom(provider))
3✔
122
                throw new ArgumentException(string.Format(Resources.Culture, Resources.NOT_IMPLEMENTED, typeof(IServiceProvider)), nameof(provider));
3✔
123

124
            if (iface.IsGenericTypeDefinition)
3✔
125
                throw new NotSupportedException(Resources.OPEN_GENERIC);
3✔
126

127
            //
128
            // Provider cannot have aspects (as it doesn't implement the service interface directly).
129
            //
130

131
            if (provider.GetCustomAttributes<AspectAttribute>(inherit: true).Any())
3✔
132
                throw new NotSupportedException(Resources.DECORATING_NOT_SUPPORTED);
3✔
133

134
            return self
3✔
135
                .Service(iface, name, provider, lifetime, options)
136
                .Decorate(static (injector, iface, instance) => ((IServiceProvider) instance).GetService(iface));
137
        }
3✔
138

139
        /// <summary>
140
        /// Registers a new service provider. Providers are "factory services" responsible for creating the concrete service:
141
        /// <code>
142
        /// class MyServiceProvider: IServiceProvider
143
        /// {
144
        ///     [Inject]
145
        ///     public IDependency Depdendency { get; init; }
146
        ///     public object GetService(Type iface) => ...;
147
        /// }
148
        /// ...
149
        /// ScopeFactory.Create
150
        /// (
151
        ///     svcs => svcs.Provider(typeof(IMyService), typeof(MyServiceProvider), Lifetime.Singleton),
152
        ///     ...
153
        /// )
154
        /// </code>
155
        /// </summary>
156
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
157
        /// <param name="iface">The interface of the service. It will be forwarded to the provider.</param>
158
        /// <param name="provider">The type of the provider. It may have dependencies and must implement the <see cref="IServiceProvider"/> interface.</param>
159
        /// <param name="lifetime">The lifetime of service.</param>
160
        /// <param name="options">Options to be assigned to the service being registered.</param>
161
        /// <remarks>The provided <see cref="IServiceProvider"/> implementation won't be disposed even if it implements the <see cref="IDisposable"/> interface.</remarks>
162
        public static IServiceCollection Provider(this IServiceCollection self, Type iface, Type provider, LifetimeBase lifetime, ServiceOptions? options = null)
163
            => self.Provider(iface, name: null, provider, lifetime, options);
3✔
164

165
        /// <summary>
166
        /// Registers a new service provider having non-interface dependency. Providers are "factory services" responsible for creating the concrete service:
167
        /// <code>
168
        /// class MyServiceProvider: IServiceProvider
169
        /// {
170
        ///     public int Depdendency { get; init; }
171
        ///     public object GetService(Type iface) => ...;
172
        /// }
173
        /// ...
174
        /// ScopeFactory.Create
175
        /// (
176
        ///     svcs => svcs.Provider(typeof(IMyService), typeof(MyServiceProvider), new { Depdendency = 1986 }, Lifetime.Singleton),
177
        ///     ...
178
        /// )
179
        /// </code>
180
        /// </summary>
181
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
182
        /// <param name="iface">The interface of the service. It will be forwarded to the provider.</param>
183
        /// <param name="provider">The type of the provider. It may have dependencies and must implement the <see cref="IServiceProvider"/> interface.</param>
184
        /// <param name="explicitArgs">Explicit arguments, provided by the user.</param>
185
        /// <param name="lifetime">The lifetime of service.</param>
186
        /// <param name="options">Options to be assigned to the service being registered.</param>
187
        /// <remarks>The provided <see cref="IServiceProvider"/> implementation won't be disposed even if it implements the <see cref="IDisposable"/> interface.</remarks>
188
        public static IServiceCollection Provider(this IServiceCollection self, Type iface, Type provider, object explicitArgs, LifetimeBase lifetime, ServiceOptions? options = null)
189
            => self.Provider(iface, null, provider, explicitArgs, lifetime, options);
3✔
190

191
        /// <summary>
192
        /// Registers a new service provider. Providers are "factory services" responsible for creating the concrete service:
193
        /// <code>
194
        /// class MyServiceProvider: IServiceProvider
195
        /// {
196
        ///     [Inject]
197
        ///     public IDependency Depdendency { get; init; }
198
        ///     public object GetService(Type iface) => ...;
199
        /// }
200
        /// ...
201
        /// ScopeFactory.Create
202
        /// (
203
        ///     svcs => svcs.Provider&lt;IMyService, MyServiceProvider&gt;("serviceName", Lifetime.Singleton),
204
        ///     ...
205
        /// )
206
        /// </code>
207
        /// </summary>
208
        /// <typeparam name="TInterface">The interface of the service. It will be forwarded to the provider.</typeparam>
209
        /// <typeparam name="TProvider">The type of the provider. It may have dependencies and must implement the <see cref="IServiceProvider"/> interface.</typeparam>
210
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
211
        /// <param name="name">The (optional) name of the service.</param>
212
        /// <param name="lifetime">The lifetime of service.</param>
213
        /// <param name="options">Options to be assigned to the service being registered.</param>
214
        /// <remarks>The provided <see cref="IServiceProvider"/> implementation won't be disposed even if it implements the <see cref="IDisposable"/> interface.</remarks>
215
        public static IServiceCollection Provider<TInterface, TProvider>(this IServiceCollection self, object? name, LifetimeBase lifetime, ServiceOptions? options = null) where TProvider : class, IServiceProvider where TInterface : class
216
            => self.Provider(typeof(TInterface), name, typeof(TProvider), lifetime, options);
3✔
217

218
        /// <summary>
219
        /// Registers a new service provider. Providers are "factory services" responsible for creating the concrete service:
220
        /// <code>
221
        /// class MyServiceProvider: IServiceProvider
222
        /// {
223
        ///     [Inject]
224
        ///     public IDependency Depdendency { get; init; }
225
        ///     public object GetService(Type iface) => ...;
226
        /// }
227
        /// ...
228
        /// ScopeFactory.Create
229
        /// (
230
        ///     svcs => svcs.Provider&lt;IMyService, MyServiceProvider&gt;(Lifetime.Singleton),
231
        ///     ...
232
        /// )
233
        /// </code>
234
        /// </summary>
235
        /// <typeparam name="TInterface">The interface of the service. It will be forwarded to the provider.</typeparam>
236
        /// <typeparam name="TProvider">The type of the provider. It may have dependencies and must implement the <see cref="IServiceProvider"/> interface.</typeparam>
237
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
238
        /// <param name="lifetime">The lifetime of service.</param>
239
        /// <param name="options">Options to be assigned to the service being registered.</param>
240
        /// <remarks>The provided <see cref="IServiceProvider"/> implementation won't be disposed even if it implements the <see cref="IDisposable"/> interface.</remarks>
241
        public static IServiceCollection Provider<TInterface, TProvider>(this IServiceCollection self, LifetimeBase lifetime, ServiceOptions? options = null) where TProvider : class, IServiceProvider where TInterface : class
242
            => self.Provider<TInterface, TProvider>(name: null, lifetime, options);
3✔
243

244
        /// <summary>
245
        /// Registers a new service provider having non-interface dependency. Providers are "factory services" responsible for creating the concrete service:
246
        /// <code>
247
        /// class MyServiceProvider: IServiceProvider
248
        /// {
249
        ///     public int Depdendency { get; init; }
250
        ///     public object GetService(Type iface) => ...;
251
        /// }
252
        /// ...
253
        /// ScopeFactory.Create
254
        /// (
255
        ///     svcs => svcs.Provider&lt;IMyService, MyServiceProvider&gt;("serviceName", new { Depdendency = 1986 }, Lifetime.Singleton),
256
        ///     ...
257
        /// )
258
        /// </code>
259
        /// </summary>
260
        /// <typeparam name="TInterface">The interface of the service. It will be forwarded to the provider.</typeparam>
261
        /// <typeparam name="TProvider">The type of the provider. It may have dependencies and must implement the <see cref="IServiceProvider"/> interface.</typeparam>
262
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
263
        /// <param name="name">The (optional) name of the service.</param>
264
        /// <param name="explicitArgs">Explicit arguments, provided by the user.</param>
265
        /// <param name="lifetime">The lifetime of service.</param>
266
        /// <param name="options">Options to be assigned to the service being registered.</param>
267
        /// <remarks>The provided <see cref="IServiceProvider"/> implementation won't be disposed even if it implements the <see cref="IDisposable"/> interface.</remarks>
268
        public static IServiceCollection Provider<TInterface, TProvider>(this IServiceCollection self, object? name, object explicitArgs, LifetimeBase lifetime, ServiceOptions? options = null) where TProvider : class, IServiceProvider where TInterface : class
269
            => self.Provider(typeof(TInterface), name, typeof(TProvider), explicitArgs, lifetime, options);
3✔
270
    }
271
}
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

© 2026 Coveralls, Inc