/
CoreServiceCollectionExtensions.cs
160 lines (134 loc) · 6.96 KB
/
CoreServiceCollectionExtensions.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using InfinniPlatform.IoC;
using InfinniPlatform.Logging;
using InfinniPlatform.Serialization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace InfinniPlatform.AspNetCore
{
/// <summary>
/// Extension methods for core dependencies registration.
/// </summary>
public static class CoreServiceCollectionExtensions
{
/// <summary>
/// Adds an application IoC-container module.
/// </summary>
/// <param name="services">Collection of registered services.</param>
/// <param name="containerModule">The application IoC-container module.</param>
public static IServiceCollection AddContainerModule(this IServiceCollection services, IContainerModule containerModule)
{
return services.AddSingleton(provider => containerModule);
}
/// <summary>
/// Adds customized MVC services.
/// </summary>
/// <param name="services">Collection of registered services.</param>
public static IMvcBuilder AddMvcWithInternalServices(this IServiceCollection services)
{
var mvcBuilder = services.AddMvc()
.AddJsonOptions(json =>
{
var settings = json.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor;
settings.NullValueHandling = NullValueHandling.Ignore;
settings.ContractResolver = new DefaultContractResolver { NamingStrategy = new DefaultNamingStrategy() };
settings.Converters.Add(new DateJsonConverter());
settings.Converters.Add(new TimeJsonConverter());
settings.Converters.Add(new DynamicDocumentJsonConverter());
});
return mvcBuilder;
}
/// <summary>
/// Builds <see cref="IServiceProvider" /> based on registered services.
/// </summary>
/// <param name="services">Collection of registered services.</param>
/// <param name="containerModules">Registered IoC-container modules.</param>
public static IServiceProvider BuildProvider(this IServiceCollection services, IEnumerable<IContainerModule> containerModules = null)
{
var options = AppOptions.Default;
return BuildProvider(services, options);
}
/// <summary>
/// Builds <see cref="IServiceProvider" /> based on registered services.
/// </summary>
/// <param name="services">Collection of registered services.</param>
/// <param name="configuration">Configuration properties set.</param>
/// <param name="containerModules">Registered IoC-container modules.</param>
public static IServiceProvider BuildProvider(this IServiceCollection services, IConfiguration configuration, IEnumerable<IContainerModule> containerModules = null)
{
var options = AppOptions.Default;
configuration.GetSection(options.SectionName).Bind(options);
return BuildProvider(services, options);
}
/// <summary>
/// Builds <see cref="IServiceProvider" /> based on registered services.
/// </summary>
/// <param name="services">Collection of registered services.</param>
/// <param name="options">Application options.</param>
/// <param name="containerModules">Registered IoC-container modules.</param>
public static IServiceProvider BuildProvider(this IServiceCollection services, AppOptions options, IEnumerable<IContainerModule> containerModules = null)
{
// Because IoC uses IHttpContextAccessor for InstancePerLifetimeScope strategy
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// For correct resolving a logger name via LoggerNameAttribute
services.AddSingleton(typeof(ILogger<>), typeof(TypedLogger<>));
services.AddSingleton(provider => new CoreContainerModule(options ?? AppOptions.Default));
if (containerModules != null)
{
foreach (var containerModule in containerModules)
{
services.AddSingleton(provider => containerModule);
}
}
var containerBuilder = new ContainerBuilder();
containerBuilder.Populate(services);
RegisterDefinedModules(containerBuilder, services);
RegisterUserModules(containerBuilder);
// ReSharper disable AccessToModifiedClosure
// Register Autofac container itself
IContainer autofacRootContainer = null;
containerBuilder.RegisterInstance((Func<IContainer>)(() => autofacRootContainer));
containerBuilder.Register(r => r.Resolve<Func<IContainer>>()()).As<IContainer>().SingleInstance();
// ReSharper restore AccessToModifiedClosure
containerBuilder.RegisterType<ContainerServiceRegistry>().As<IContainerServiceRegistry>().SingleInstance();
containerBuilder.RegisterType<ServiceProviderAccessor>().As<IServiceProviderAccessor>().SingleInstance();
containerBuilder.RegisterType<ContainerResolver>().As<IContainerResolver>().SingleInstance();
autofacRootContainer = containerBuilder.Build();
return new AutofacServiceProvider(autofacRootContainer);
}
private static void RegisterDefinedModules(ContainerBuilder containerBuilder, IServiceCollection services)
{
var modules = services.Where(service => typeof(IContainerModule).IsAssignableFrom(service.ServiceType));
foreach (var module in modules)
{
var containerModule = (IContainerModule) module.ImplementationFactory.Invoke(null);
var autofacContainerModule = new AutofacContainerModule(containerModule);
containerBuilder.RegisterModule(autofacContainerModule);
}
}
private static void RegisterUserModules(ContainerBuilder containerBuilder)
{
var modules = Assembly.GetEntryAssembly()
.GetTypes()
.Where(type => typeof(IContainerModule).IsAssignableFrom(type));
foreach (var module in modules)
{
var containerModule = (IContainerModule) Activator.CreateInstance(module);
var autofacContainerModule = new AutofacContainerModule(containerModule);
containerBuilder.RegisterModule(autofacContainerModule);
}
}
}
}