我们知道整个ASP.NET Core建立在以ServiceCollection/ServiceProvider为核心的DI框架上,它甚至提供了扩展点使我们可以与第三方DI框架进行整合。对此比较了解的读者朋友应该很清楚,针对第三方DI框架的整合可以通过在定义Startup类型的ConfigureServices方法返回一个ServiceProvider来实现。但是真的有这么简单吗?
一、ConfigureServices方法返回的ServiceProvider貌似没有用!?
我们可以通过一个简单的实例来说明这个问题。我们先定义了如下这个一个MyServiceProvider,它实际上是对另一个ServiceProvider的封装。简单起见,我们利用一个字典来保存服务接口与实现类型的映射关系,这个关系可以通过调用Registe方法来注册。在提供服务实例的GetService方法中,如果提供的服务类型已经被注册,我们会创建并返回对应的实例对象,否则我们将利用封装的这个ServiceProvider来提供服务。为了确保服务实例能够被正常回收,如果服务类型实现了IDisposable接口,我们会将它添加到通过字段_disposables表示的集合中。当MyServiceProvider的Dispose方法被调用的时候,提供的这些服务实例的Dispose方法会被调用。
1: public class MyServiceProvider : IServiceProvider,IDisposable
2: {
3: private IServiceProvider _innerServiceProvider;
4: private Dictionary<Type,Type> _services;
5: private List<IDisposable> _disposables;
6:
7: public MyServiceProvider(IServiceProvider innerServiceProvider)
8: {
9: _innerServiceProvider = innerServiceProvider;
10: this._services = new Dictionary<Type,Type>();
11: _disposables = new List<IDisposable>();
12: }
13:
14:
15: public MyServiceProvider Register<TFrom,TTo>() where TTo: TFrom,new()
16: {
17: _services[typeof(TFrom)] = typeof(TTo);
18: return this;
19: }
20:
21: object GetService(Type serviceType)
22: {
23: Type implementation;
24: if (_services.TryGetValue(serviceType,1)">out implementation))
25: {
26: object service = Activator.CreateInstance(implementation);
27: IDisposable disposbale = service as IDisposable;
28: if (null != disposbale)
29: {
30: _disposables.Add(disposbale);
31: }
32: return service;
33: }
34: return _innerServiceProvider.GetService(serviceType);
35: }
36:
37: void Dispose()
38: {
39: (_innerServiceProvider as IDisposable)?.Dispose();
40: foreach (var it in _disposables)
41: {
42: it.Dispose();
43: }
44: _disposables.Clear();
45: }
46: }
我们按照如下的方式在一个ASP.NET Core应用中使用MyServiceProvider。如下面的代码片断中,在注册的Starup类型中,我们让ConfigureServices方法返回一个MyServiceProvider对象。服务接口IFoobar和实现类型Foobar之间的映射注册在这个MyServiceProvider对象上。在处理请求的时候,我们利用当前HttpContext对象的RequestServices属性得到为请求处理提供服务的ServiceProvider,并试图利用它得到注册的IFoobar服务。
5: new WebHostBuilder()
7: .UseStartup<Startup>()
9: .Run();
11: }
13: class Startup
public IServiceProvider ConfigureServices(IServiceCollection services)
18: .Register<IFoobar,Foobar>();
23: app.UseDeveloperExceptionPage()
25: }
27: interface IFoobar { }
internal class ServiceScope : IServiceScope
4:
6: {
8: }
10: {
14: 15: {
17: }
19:
21: {
23: 24:
27: _innerServiceFactory = innerServiceFactory;
29: }
31: {
33: }
public MyServiceProvider(IServiceProvider innerServiceProvider,1)"> 5: _innerServiceProvider = innerServiceProvider;
7: _disposables = 9:
12: if (serviceType == typeof(IServiceScopeFactory))
14: IServiceScopeFactory innerServiceScopeFactory = _innerServiceProvider.GetRequiredService<IServiceScopeFactory>();
17: ...
19: ...