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

Sholtee / injector / 2251

27 Dec 2023 10:00AM UTC coverage: 90.723% (-2.0%) from 92.704%
2251

push

appveyor

Sholtee
Merge branch 'drop_opencover'

2171 of 2393 relevant lines covered (90.72%)

0.91 hits per line

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

93.48
/SRC/Injector/Public/Extensions/IServiceCollectionAdvancedExtensions/Decorate.cs
1
/********************************************************************************
2
* Decorate.cs                                                                   *
3
*                                                                               *
4
* Author: Denes Solti                                                           *
5
********************************************************************************/
6
using System;
7
using System.Collections.Generic;
8
using System.Linq;
9

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

15
    public static partial class IServiceCollectionAdvancedExtensions
16
    {
17
        /// <summary>
18
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
19
        /// </summary>
20
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
21
        /// <param name="interceptors">The interceptors to be applied.</param>
22
        /// <remarks>
23
        /// <list type="bullet">
24
        /// <item>You can't create proxies against instances and open generic services.</item>
25
        /// <item>A service can be decorated multiple times.</item>
26
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
27
        /// </list>
28
        /// Using this method is the preferred way to apply multiple interceptors against the same service as it will only create one backing proxy.
29
        /// </remarks>
30
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
31
        public static IServiceCollection Decorate(this IServiceCollection self, IEnumerable<(Type Interceptor, object? ExplicitArg)> interceptors)
32
        {
1✔
33
            if (self is null)
1✔
34
                throw new ArgumentNullException(nameof(self));
1✔
35

36
            if (interceptors is null)
1✔
37
                throw new ArgumentNullException(nameof(interceptors));
×
38

39
            self.Last().ApplyInterceptors(interceptors);
1✔
40
            return self;
1✔
41
        }
1✔
42

43
        /// <summary>
44
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
45
        /// </summary>
46
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
47
        /// <param name="interceptors">The interceptors to be applied.</param>
48
        /// <remarks>
49
        /// <list type="bullet">
50
        /// <item>You can't create proxies against instances and open generic services.</item>
51
        /// <item>A service can be decorated multiple times.</item>
52
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
53
        /// </list>
54
        /// Using this method is the preferred way to apply multiple interceptors against the same service as it will only create one backing proxy.
55
        /// </remarks>
56
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
57
        public static IServiceCollection Decorate(this IServiceCollection self, params (Type Interceptor, object? ExplicitArg)[] interceptors) =>
58
            self.Decorate((IEnumerable<(Type, object?)>) interceptors);
1✔
59

60
        /// <summary>
61
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
62
        /// </summary>
63
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
64
        /// <param name="interceptors">The interceptors to be applied.</param>
65
        /// <remarks>
66
        /// <list type="bullet">
67
        /// <item>You can't create proxies against instances and open generic services.</item>
68
        /// <item>A service can be decorated multiple times.</item>
69
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
70
        /// </list>
71
        /// Using this method is the preferred way to apply multiple interceptors against the same service as it will only create one backing proxy.
72
        /// </remarks>
73
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
74
        public static IServiceCollection Decorate(this IServiceCollection self, params Type[] interceptors) => self.Decorate
1✔
75
        (
1✔
76
            interceptors.Select
1✔
77
            (
1✔
78
                static i => (i, (object?) null)
1✔
79
            )
1✔
80
        );
1✔
81

82
        /// <summary>
83
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
84
        /// </summary>
85
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
86
        /// <param name="interceptor">The interceptor type.</param>
87
        /// <param name="explicitArgs">Explicit arguments to be passed.</param>
88
        /// <remarks>
89
        /// <list type="bullet">
90
        /// <item>You can't create proxies against instances and open generic services.</item>
91
        /// <item>A service can be decorated multiple times.</item>
92
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
93
        /// </list>
94
        /// </remarks>
95
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
96
        public static IServiceCollection Decorate(this IServiceCollection self, Type interceptor, object? explicitArgs) =>
97
            self.Decorate(new[] { (interceptor, explicitArgs) });
1✔
98

99
        /// <summary>
100
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
101
        /// </summary>
102
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
103
        /// <param name="interceptor">The interceptor type.</param>
104
        /// <remarks>
105
        /// <list type="bullet">
106
        /// <item>You can't create proxies against instances and open generic services.</item>
107
        /// <item>A service can be decorated multiple times.</item>
108
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
109
        /// </list>
110
        /// </remarks>
111
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
112
        public static IServiceCollection Decorate(this IServiceCollection self, Type interceptor) =>
113
            self.Decorate(new[] { interceptor });
1✔
114

115
        /// <summary>
116
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
117
        /// </summary>
118
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
119
        /// <remarks>
120
        /// <list type="bullet">
121
        /// <item>You can't create proxies against instances and open generic services.</item>
122
        /// <item>A service can be decorated multiple times.</item>
123
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
124
        /// </list>
125
        /// </remarks>
126
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
127
        public static IServiceCollection Decorate<TInterceptor>(this IServiceCollection self) where TInterceptor : IInterfaceInterceptor =>
128
            self.Decorate(new[] { typeof(TInterceptor) });
1✔
129

130
        /// <summary>
131
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
132
        /// </summary>
133
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
134
        /// <param name="type">The service type.</param>
135
        /// <param name="key">The (optional) service key (usually a name).</param>
136
        /// <param name="interceptors">Interceptors to be applied.</param>
137
        /// <remarks>
138
        /// <list type="bullet">
139
        /// <item>You can't create proxies against instances and open generic services.</item>
140
        /// <item>A service can be decorated multiple times.</item>
141
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
142
        /// </list>
143
        /// Using this method is the preferred way to apply multiple interceptors against the same service as it will only create one backing proxy.
144
        /// </remarks>
145
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
146
        public static IServiceCollection Decorate(this IServiceCollection self, Type type, object? key, IEnumerable<(Type Interceptor, object? ExplicitArg)> interceptors)
147
        {
1✔
148
            if (self is null)
1✔
149
                throw new ArgumentNullException(nameof(self));
1✔
150

151
            if (type is null)
1✔
152
                throw new ArgumentNullException(nameof(type));
1✔
153

154
            if (interceptors is null)
1✔
155
                throw new ArgumentNullException(nameof(interceptors));
×
156

157
            self.Find(type, key).ApplyInterceptors(interceptors);
1✔
158
            return self;
1✔
159
        }
1✔
160

161
        /// <summary>
162
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
163
        /// </summary>
164
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
165
        /// <param name="type">The service type.</param>
166
        /// <param name="key">The (optional) service key (usually a name).</param>
167
        /// <param name="interceptors">Interceptors to be applied.</param>
168
        /// <remarks>
169
        /// <list type="bullet">
170
        /// <item>You can't create proxies against instances and open generic services.</item>
171
        /// <item>A service can be decorated multiple times.</item>
172
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
173
        /// </list>
174
        /// Using this method is the preferred way to apply multiple interceptors against the same service as it will only create one backing proxy.
175
        /// </remarks>
176
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
177
        public static IServiceCollection Decorate(this IServiceCollection self, Type type, object? key, params (Type Interceptor, object? ExplicitArg)[] interceptors) =>
178
            self.Decorate(type, key, (IEnumerable<(Type, object?)>) interceptors);
1✔
179

180
        /// <summary>
181
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
182
        /// </summary>
183
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
184
        /// <param name="type">The service type.</param>
185
        /// <param name="key">The (optional) service key (usually a name).</param>
186
        /// <param name="interceptors">Interceptors to be applied.</param>
187
        /// <remarks>
188
        /// <list type="bullet">
189
        /// <item>You can't create proxies against instances and open generic services.</item>
190
        /// <item>A service can be decorated multiple times.</item>
191
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
192
        /// </list>
193
        /// Using this method is the preferred way to apply multiple interceptors against the same service as it will only create one backing proxy.
194
        /// </remarks>
195
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
196
        public static IServiceCollection Decorate(this IServiceCollection self, Type type, object? key, params Type[] interceptors) => self.Decorate
1✔
197
        (
1✔
198
            type,
1✔
199
            key,
1✔
200
            interceptors.Select
1✔
201
            (
1✔
202
                static interceptor => (interceptor, (object?) null)
1✔
203
            )
1✔
204
        );
1✔
205

206
        /// <summary>
207
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
208
        /// </summary>
209
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
210
        /// <param name="type">The service type.</param>
211
        /// <param name="key">The (optional) service key (usually a name).</param>
212
        /// <param name="interceptor">The interceptor type.</param>
213
        /// <param name="explicitArgs">Explicit arguments to be passed.</param>
214
        /// <remarks>
215
        /// <list type="bullet">
216
        /// <item>You can't create proxies against instances and open generic services.</item>
217
        /// <item>A service can be decorated multiple times.</item>
218
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
219
        /// </list>
220
        /// </remarks>
221
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
222
        public static IServiceCollection Decorate(this IServiceCollection self, Type type, object? key, Type interceptor, object? explicitArgs) =>
223
            self.Decorate(type, key, new[] { (interceptor, explicitArgs) });
1✔
224

225
        /// <summary>
226
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
227
        /// </summary>
228
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
229
        /// <param name="type">The service type.</param>
230
        /// <param name="key">The (optional) service key (usually a name).</param>
231
        /// <param name="interceptor">The interceptor type.</param>
232
        /// <remarks>
233
        /// <list type="bullet">
234
        /// <item>You can't create proxies against instances and open generic services.</item>
235
        /// <item>A service can be decorated multiple times.</item>
236
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
237
        /// </list>
238
        /// </remarks>
239
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
240
        public static IServiceCollection Decorate(this IServiceCollection self, Type type, object? key, Type interceptor) =>
241
            self.Decorate(type, key, new[] { interceptor });
1✔
242

243
        /// <summary>
244
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
245
        /// </summary>
246
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
247
        /// <param name="type">The service type.</param>
248
        /// <param name="interceptor">The interceptor type.</param>
249
        /// <param name="explicitArgs">Explicit arguments to be passed.</param>
250
        /// <remarks>
251
        /// <list type="bullet">
252
        /// <item>You can't create proxies against instances and open generic services.</item>
253
        /// <item>A service can be decorated multiple times.</item>
254
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
255
        /// </list>
256
        /// </remarks>
257
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
258
        public static IServiceCollection Decorate(this IServiceCollection self, Type type, Type interceptor, object? explicitArgs) =>
259
            self.Decorate(type, null, interceptor, explicitArgs);
×
260

261
        /// <summary>
262
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
263
        /// </summary>
264
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
265
        /// <param name="type">The service type.</param>
266
        /// <param name="interceptor">The interceptor type.</param>
267
        /// <remarks>
268
        /// <list type="bullet">
269
        /// <item>You can't create proxies against instances and open generic services.</item>
270
        /// <item>A service can be decorated multiple times.</item>
271
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
272
        /// </list>
273
        /// </remarks>
274
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
275
        public static IServiceCollection Decorate(this IServiceCollection self, Type type, Type interceptor) =>
276
            self.Decorate(type, key: null, new[] { interceptor });
1✔
277

278
        /// <summary>
279
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
280
        /// </summary>
281
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
282
        /// <param name="key">The (optional) service key (usually a name).</param>
283
        /// <param name="explicitArgs">Explicit arguments to be passed.</param>
284
        /// <remarks>
285
        /// <list type="bullet">
286
        /// <item>You can't create proxies against instances and open generic services.</item>
287
        /// <item>A service can be decorated multiple times.</item>
288
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
289
        /// </list>
290
        /// </remarks>
291
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
292
        public static IServiceCollection Decorate<TType, TInterceptor>(this IServiceCollection self, object? key, object? explicitArgs) where TType : class where TInterceptor : IInterfaceInterceptor
293
            => self.Decorate(typeof(TType), key, typeof(TInterceptor), explicitArgs);
1✔
294

295
        /// <summary>
296
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
297
        /// </summary>
298
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
299
        /// <param name="key">The (optional) service key (usually a name).</param>
300
        /// <remarks>
301
        /// <list type="bullet">
302
        /// <item>You can't create proxies against instances and open generic services.</item>
303
        /// <item>A service can be decorated multiple times.</item>
304
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
305
        /// </list>
306
        /// </remarks>
307
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
308
        public static IServiceCollection Decorate<TType, TInterceptor>(this IServiceCollection self, object? key) where TType: class where TInterceptor: IInterfaceInterceptor
309
            => self.Decorate(typeof(TType), key, typeof(TInterceptor));
1✔
310

311
        /// <summary>
312
        /// Hooks into the instantiating process to let you decorate the original service. Useful when you want to add additional functionality (e.g. parameter validation).
313
        /// </summary>
314
        /// <param name="self">The target <see cref="IServiceCollection"/>.</param>
315
        /// <remarks>
316
        /// <list type="bullet">
317
        /// <item>You can't create proxies against instances and open generic services.</item>
318
        /// <item>A service can be decorated multiple times.</item>
319
        /// <item>Wrapping a service into an interceptor implies that it cannot be disposed unless the service interface itself implements the <see cref="IDisposable"/>.</item>
320
        /// </list>
321
        /// </remarks>
322
        /// <exception cref="NotSupportedException">When proxying is not allowed (see remarks).</exception>
323
        public static IServiceCollection Decorate<TType, TInterceptor>(this IServiceCollection self) where TType : class where TInterceptor : IInterfaceInterceptor
324
            => self.Decorate(typeof(TType), typeof(TInterceptor));
1✔
325
    }
326
}
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