-
Notifications
You must be signed in to change notification settings - Fork 4
/
ServiceCollectionExtensions.cs
126 lines (108 loc) · 5.59 KB
/
ServiceCollectionExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System;
using System.Linq;
using Castle.DynamicProxy;
using Foil.Conventions;
using Foil.Interceptions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Foil
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddTransientWithInterception<T, TImplementation>(
this IServiceCollection services,
Func<IServiceProvider, TImplementation> serviceFactory,
Action<IInterceptBy> configurator)
where T : class where TImplementation : class, T
{
if (services == null)
throw new ArgumentNullException(nameof(services));
if (serviceFactory == null)
throw new ArgumentNullException(nameof(serviceFactory));
return services.Add<T, TImplementation>(
lifetime => new ServiceDescriptor(typeof(TImplementation), serviceFactory, lifetime),
configurator, ServiceLifetime.Transient);
}
public static IServiceCollection AddScopedWithInterception<T, TImplementation>(this IServiceCollection services,
Func<IServiceProvider, TImplementation> serviceFactory,
Action<IInterceptBy> configurator)
where T : class where TImplementation : class, T
{
if (services == null)
throw new ArgumentNullException(nameof(services));
if (serviceFactory == null)
throw new ArgumentNullException(nameof(serviceFactory));
return services.Add<T, TImplementation>(
lifetime => new ServiceDescriptor(typeof(TImplementation), serviceFactory, lifetime),
configurator, ServiceLifetime.Scoped);
}
public static IServiceCollection AddSingletonWithInterception<T, TImplementation>(
this IServiceCollection services,
Func<IServiceProvider, TImplementation> serviceFactory,
Action<IInterceptBy> configurator)
where T : class where TImplementation : class, T
{
if (services == null)
throw new ArgumentNullException(nameof(services));
if (serviceFactory == null)
throw new ArgumentNullException(nameof(serviceFactory));
return services.Add<T, TImplementation>(
lifetime => new ServiceDescriptor(typeof(TImplementation), serviceFactory, lifetime),
configurator, ServiceLifetime.Singleton);
}
public static IServiceCollection AddTransientWithInterception<T, TImplementation>(
this IServiceCollection services, Action<IInterceptBy> configurator)
where T : class
where TImplementation : class, T
{
return Add<T, TImplementation>(services,
lifetime => ServiceDescriptor.Describe(typeof(TImplementation), typeof(TImplementation), lifetime),
configurator, ServiceLifetime.Transient);
}
public static IServiceCollection AddScopedWithInterception<T, TImplementation>(
this IServiceCollection services, Action<IInterceptBy> configurator)
where T : class
where TImplementation : class, T
{
return Add<T, TImplementation>(services,
lifetime => ServiceDescriptor.Describe(typeof(TImplementation), typeof(TImplementation), lifetime),
configurator, ServiceLifetime.Scoped);
}
public static IServiceCollection AddSingletonWithInterception<T, TImplementation>(
this IServiceCollection services, Action<IInterceptBy> configurator)
where T : class
where TImplementation : class, T
{
if (services == null) throw new ArgumentNullException(nameof(services));
return Add<T, TImplementation>(services,
lifetime => ServiceDescriptor.Describe(typeof(TImplementation), typeof(TImplementation), lifetime),
configurator, ServiceLifetime.Singleton);
}
private static IServiceCollection Add<TService, TImplementation>(this IServiceCollection services,
Func<ServiceLifetime, ServiceDescriptor> descriptorFactory, Action<IInterceptBy> configurator,
ServiceLifetime lifetime) where TService : class where TImplementation : class, TService
{
if (services == null)
throw new ArgumentNullException(nameof(services));
if (configurator == null) throw new ArgumentNullException(nameof(configurator));
var interceptionOptions = new InterceptionOptions();
configurator.Invoke(interceptionOptions);
interceptionOptions.Interceptors.ForEach(services.TryAddTransient);
services.TryAdd(descriptorFactory(lifetime));
services.AddTransient(sp =>
{
var interceptorInstances = interceptionOptions.Interceptors
.Select(sp.GetRequiredService)
.Cast<IInterceptor>()
.ToArray();
var implementation = sp.GetRequiredService<TImplementation>();
var proxyFactory = new ProxyGenerator();
var proxyGenerationHook = new ConventionBasedProxyGenerationHook(interceptionOptions.Convention);
var proxyGenerationOptions = new ProxyGenerationOptions(proxyGenerationHook);
return proxyFactory.CreateInterfaceProxyWithTarget<TService>(implementation, proxyGenerationOptions,
interceptorInstances);
});
return services;
}
}
}