一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - ASP.NET教程 - ASP.NET Core應(yīng)用中與第三方IoC/DI框架的整合

ASP.NET Core應(yīng)用中與第三方IoC/DI框架的整合

2020-04-30 12:41蔣金楠 ASP.NET教程

ASP.NET Core應(yīng)用中,針對第三方DI框架的整合可以通過在定義Startup類型的ConfigureServices方法返回一個ServiceProvider來實(shí)現(xiàn)。但是并不是那么容易的,下面通過實(shí)例給大家分享一下

一、ConfigureServices方法返回的ServiceProvider沒有用!

我們可以通過一個簡單的實(shí)例來說明這個問題。我們先定義了如下這個一個MyServiceProvider,它實(shí)際上是對另一個ServiceProvider的封裝。簡單起見,我們利用一個字典來保存服務(wù)接口與實(shí)現(xiàn)類型的映射關(guān)系,這個關(guān)系可以通過調(diào)用Registe方法來注冊。在提供服務(wù)實(shí)例的GetService方法中,如果提供的服務(wù)類型已經(jīng)被注冊,我們會創(chuàng)建并返回對應(yīng)的實(shí)例對象,否則我們將利用封裝的這個ServiceProvider來提供服務(wù)。為了確保服務(wù)實(shí)例能夠被正常回收,如果服務(wù)類型實(shí)現(xiàn)了IDisposable接口,我們會將它添加到通過字段_disposables表示的集合中。當(dāng)MyServiceProvider的Dispose方法被調(diào)用的時候,提供的這些服務(wù)實(shí)例的Dispose方法會被調(diào)用。

?
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
public class MyServiceProvider : IServiceProvider, IDisposable
{
private IServiceProvider _innerServiceProvider;
private Dictionary<Type, Type> _services;
private List<IDisposable> _disposables;
 
public MyServiceProvider(IServiceProvider innerServiceProvider)
{
_innerServiceProvider = innerServiceProvider;
this._services = new Dictionary<Type, Type>();
_disposables = new List<IDisposable>();
}
 
 
public MyServiceProvider Register<TFrom, TTo>() where TTo: TFrom, new()
{
_services[typeof(TFrom)] = typeof(TTo);
return this;
}
 
public object GetService(Type serviceType)
{
Type implementation;
if (_services.TryGetValue(serviceType, out implementation))
{
object service = Activator.CreateInstance(implementation);
IDisposable disposbale = service as IDisposable;
if (null != disposbale)
{
 _disposables.Add(disposbale);
}
return service;
}
return _innerServiceProvider.GetService(serviceType);
}
 
public void Dispose()
{
(_innerServiceProvider as IDisposable)?.Dispose();
foreach (var it in _disposables)
{
it.Dispose();
}
_disposables.Clear();
}
}

我們按照如下的方式在一個ASP.NET Core應(yīng)用中使用MyServiceProvider。如下面的代碼片斷中,在注冊的Starup類型中,我們讓ConfigureServices方法返回一個MyServiceProvider對象。服務(wù)接口IFoobar和實(shí)現(xiàn)類型Foobar之間的映射注冊在這個MyServiceProvider對象上。在處理請求的時候,我們利用當(dāng)前HttpContext對象的RequestServices屬性得到為請求處理提供服務(wù)的ServiceProvider,并試圖利用它得到注冊的IFoobar服務(wù)。

?
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
public class Program
{
public static void Main(string[] args)
{
new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Build()
.Run();
}
}
 
public class Startup
{
public IServiceProvider ConfigureServices(IServiceCollection services)
{
return new MyServiceProvider(services.BuildServiceProvider())
.Register<IFoobar, Foobar>();
}
 
public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage()
.Run(async context => await context.Response.WriteAsync(context.RequestServices.GetRequiredService<IFoobar>().GetType().Name));
}
}
public interface IFoobar { }
public class Foobar : IFoobar { }

整個應(yīng)用就這樣簡單,貌似也沒有什么問題,但是我們啟動應(yīng)用并利用瀏覽器訪問該應(yīng)用是就會出現(xiàn)如下所示的錯誤。錯誤信息表示服務(wù)接口IFoobar尚未被注冊。

ASP.NET Core應(yīng)用中與第三方IoC/DI框架的整合

二、原因何在?

我們明明在返回的ServiceProvider注冊了IFoobar和Foobar之間的映射關(guān)系,為什么RequestServices返回的ServiceProvider說該服務(wù)尚未被注冊呢?唯一的解釋就是ConfigureServices方法返回的ServiceProvider與HttpContext的RequestServices返回的ServiceProvider根本就不是同一個。實(shí)際上它們本來就不是同一個對象。

ConfigureServices方法返回的ServiceProvider將會作為WebHost的ServiceProvider,對于每次接收的請求,WebHost會根據(jù)這個ServiceProvider創(chuàng)建一個新的ServiceProvider來作為HttpContext的RequestServices屬性,這兩個ServiceProvider具有父子管理。照例說,如果RequestServices返回的ServiceProvider是根據(jù)ConfigureServices方法返回的ServiceProvider創(chuàng)建的,那么它也應(yīng)該能夠識別注冊的服務(wù)類型IFoobar,那么為什么依然會出現(xiàn)錯誤呢?

要了解這個問題,就需要知道這個所謂的“子ServiceProvider”是如何被創(chuàng)建出來的,這其中涉及到ServiceScope的概念。簡單來說,ServiceScope是對一個ServiceProvider的封裝,前者決定后者的生命周期。ServiceScope由ServiceScopeFactory創(chuàng)建,后者以一個服務(wù)的形式注冊到“父ServiceProvider”上面。當(dāng)“父ServiceProvider”需要創(chuàng)建“子ServiceProvider”的時候,它會調(diào)用GetService方法得到這個ServiceScopeFactory對象(采用的服務(wù)接口為IServiceScopeFactory),并利用后者創(chuàng)建一個ServiceScope,這個ServiceScope提供的ServiceProvider就是返回的“子ServiceProvider”。

但是對于我們的MyServiceProvider對象來說,當(dāng)調(diào)用它的GetService方法試圖獲取ServiceScopeFactory對象的時候,獲取的實(shí)際上是被封裝的那個SerivceProvider關(guān)聯(lián)的ServiceScopeFactory,那么很自然創(chuàng)建的“子ServiceProvider”也與MyServiceProvider沒有什么關(guān)系。

三、如何解決這個問題?

既然我們知道了問題的根源,我們自然就有了解決方案。解決方案并不復(fù)雜,我們只需要MyServiceProvider的GetService方法返回反映其自身服務(wù)注冊相關(guān)的ServiceScopeFactory。為此我們定義了如下一個ServiceScope和對應(yīng)的ServiceScopeFactory。

?
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
internal class ServiceScope : IServiceScope
{
private MyServiceProvider _serviceProvider;
 
public ServiceScope(IServiceScope innserServiceScope, Dictionary<Type, Type> services)
{
_serviceProvider = new MyServiceProvider(innserServiceScope.ServiceProvider, services);
}
public IServiceProvider ServiceProvider
{
get { return _serviceProvider; }
}
 
public void Dispose()
{
_serviceProvider.Dispose();
}
}
 
internal class ServiceScopeFactory : IServiceScopeFactory
{
private IServiceScopeFactory _innerServiceFactory;
private Dictionary<Type, Type> _services;
 
public ServiceScopeFactory(IServiceScopeFactory innerServiceFactory, Dictionary<Type, Type> services)
{
_innerServiceFactory = innerServiceFactory;
_services = services;
}
public IServiceScope CreateScope()
{
return new ServiceScope(_innerServiceFactory.CreateScope(), _services);
}
}

除此之外,我們?yōu)镸yServiceProvider添加了一個構(gòu)造函數(shù),GetService方法也針對IServiceScopeFactory添加了相應(yīng)的代碼。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MyServiceProvider : IServiceProvider, IDisposable
{
 public MyServiceProvider(IServiceProvider innerServiceProvider, Dictionary<Type, Type> services)
 {
 _innerServiceProvider = innerServiceProvider;
 _services = services;
 _disposables = new List<IDisposable>();
 }
 
 public object GetService(Type serviceType)
 {
 if (serviceType == typeof(IServiceScopeFactory))
 {
 IServiceScopeFactory innerServiceScopeFactory = _innerServiceProvider.GetRequiredService<IServiceScopeFactory>();
 return new ServiceScopeFactory(innerServiceScopeFactory, _services);
 }
 ...
 }
 ...
 }

以上分享,希望能對需要解決這樣問題的朋友有所幫助!

原文鏈接:http://www.cnblogs.com/artech/p/3rd-party-di-integration.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: m3u8久久国产精品影院 | 青青青国产视频 | 精品视频一区二区三区 | 亚洲欧美精品久久 | a一级毛片录像带 录像片 | 奇米影视4444 | 国产福利视频一区二区微拍 | 香蕉久久网 | 成功精品影院 | 国自产在线精品免费 | 热久久免费视频 | porno movie hd高清| 丰腴尤物贵妇浪荡小说 | 王小军怎么了最新消息 | 亚洲国产韩国欧美在线不卡 | 国产麻豆剧果冻传媒影视4934 | www国产精品| 日本一二线不卡在线观看 | 亚洲午夜小视频 | 久久精品无码人妻无码AV蜜臀 | 美女被的视频 | 四虎影音先锋 | 亚洲第一区欧美日韩精品 | 亚洲精选在线观看 | 亚色九九九全国免费视频 | 青青青国产精品国产精品久久久久 | 亚洲国产在 | 情趣内衣情趣玩具play | 国产全部理论片线观看 | 草逼视频网址 | 色综合网天天综合色中文男男 | 精品一区二区三区免费观看 | 91爱啪| 三级全黄裸体 | 牛人国产偷窥女洗浴在线观看 | 美女和男人一起差差 | 香蕉久久久久久狠狠色 | www.午夜剧场| 国内精品视频一区二区三区八戒 | xnxx18美女 | 免费看60分钟大片视频播放 |