IHostingEnvironment VS IHostEnvironment - .NET Core 3.0中的廢棄類型

原文: IHostingEnvironment VS IHostEnvironment - .NET Core 3.0中的廢棄類型

原文: https://andrewlock.net/ihostingenvironment-vs-ihost-environment-obsolete-types-in-net-core-3/
做者: Andrew Lock
譯者: Lamond Luhtml

本篇是如何升級到ASP.NET Core 3.0系列文章的第二篇。java

在本篇博客中,我將描述與以前版本相比,ASP.NET Core 3.0中已經被標記爲廢棄的類型。我將解釋一下爲何這些類型被廢棄了,它們的替換類型是什麼,以及你應該何時使用它們。web


ASP.NET Core與通用主機(Generic Host)合併#

在ASP.NET Core 2.1中引入了新的通用主機(Generic Host), 它是藉助Microsoft.Extension.*程序集來進行程序配置,依賴注入,以及日誌記錄來構建非HTTP應用的一種方式。 雖然這是一個至關不錯的點子,可是引入主機抽象在基礎上與ASP.NET Core使用的HTTP主機不兼容。這致使了多種命名空間的衝突與不兼容,因此在ASP.NET Core 2.x版本中,我一直儘可能不使用通用主機。c#

在ASP.NET Core 3.0中,開發人員做出了巨大的努力,將Web主機與通用主機兼容起來。ASP.NET Core的Web主機如今能夠做爲IHostedService運行在通用主機中,重複抽象的問題(ASP.NET Core中使用一套抽象,通用主機使用另外一套抽象)獲得了根本解決。服務器

固然,這還不是所有。當你從ASP.NET Core 2.x升級到3.0, ASP.NET Core 3.0並不強迫你當即使用新的通用主機。若是你願意,你能夠繼續使用舊的WebHostBuilder,而不使用新的HostBuilder。雖然在ASP.NET Core 3.0的官方文檔中一直暗示這是必須的,可是在當前的階段,這是一個可選配置,若是你須要,能夠繼續使用Web主機,而不使用通用主機。app

PS: 不過我仍是建議你將可能將HostBuilder做爲你將來的升級計劃。我可是在將來的某個時間點WebHostBuilder將被移除,即便如今它尚未被標記爲[Obsolete]ide

做爲重構的通用主機的一部分,一些在以前版本中重複的類型被標記爲廢棄了,一些新的類型被引入了。在這些類型中,最好的例子就是IHostingEnvironmentvisual-studio

IHostingEnvironment VS IHostEnvironment VS IWebHostEnviornment#

IHostingEnvironment是.NET Core 2.x中最讓人討厭的一個接口,由於它存在於兩個命名空間中, Microsoft.AspNetCore.HostingMicrosoft.Extensions.Hosting.這兩個接口有少量不一樣,且不兼容。測試

 
 
 
 
 
 
Copy
namespace Microsoft.AspNetCore.Hosting { public interface IHostingEnvironment { string EnvironmentName { get; set; } string ApplicationName { get; set; } string WebRootPath { get; set; } IFileProvider WebRootFileProvider { get; set; } string ContentRootPath { get; set; } IFileProvider ContentRootFileProvider { get; set; } } } namespace Microsoft.Extensions.Hosting { public interface IHostingEnvironment { string EnvironmentName { get; set; } string ApplicationName { get; set; } string ContentRootPath { get; set; } IFileProvider ContentRootFileProvider { get; set; } } }

之因此有兩個同名接口是有歷史緣由的。AspNetCore版本的接口已經存在了很長時間了,在ASP.NET Core 2.1版本中,通用主機引入了Extensions版本。Extensions版本沒有提供用於服務靜態文件的wwwroot目錄的概念(由於它承載的是非HTTP服務)。因此你可能已經注意到Extensions缺乏了WebRootFileProviderWebRootPath兩個屬性。ui

出於向後兼容的緣由,這裏須要一個單獨的抽象。可是,這種作法真正使人討厭的後果之一是沒法編寫用於通用主機和ASP.NET Core的擴展方法。

在ASP.NET Core 3.0中,上述的兩個接口都已經被標記爲廢棄了。你依然可使用它們,可是在編譯的時候,你會獲得一些警告。相對的,兩個新的接口被引入進來: IHostEnvironmentIWebHostEnvironment。雖然他們出如今不一樣的命名空間中,可是如今它們有了不一樣的名字,並且使用了繼承關係。

 
 
 
 
 
 
Copy
namespace Microsoft.Extensions.Hosting { public interface IHostEnvironment { string EnvironmentName { get; set; } string ApplicationName { get; set; } string ContentRootPath { get; set; } IFileProvider ContentRootFileProvider { get; set; } } } namespace Microsoft.AspNetCore.Hosting { public interface IWebHostEnvironment : IHostEnvironment { string WebRootPath { get; set; } IFileProvider WebRootFileProvider { get; set; } } }

這個層次關係更容易理解了,避免了重複,而且意味着接收通用主機版本宿主環境抽象(IHostEnvironment)的方法如今也能夠接收web版本(IWebHostEnvironment)的抽象了。在幕後,IHostEnvironmentIWebHostEnvironment的實現是相同的 - 除了舊接口,他們還實現了新接口。

例如,ASP.NET Core的實現類以下:

 
 
 
 
 
 
Copy
namespace Microsoft.AspNetCore.Hosting { internal class HostingEnvironment : IHostingEnvironment, Extensions.Hosting.IHostingEnvironment, IWebHostEnvironment { public string EnvironmentName { get; set; } = Extensions.Hosting.Environments.Production; public string ApplicationName { get; set; } public string WebRootPath { get; set; } public IFileProvider WebRootFileProvider { get; set; } public string ContentRootPath { get; set; } public IFileProvider ContentRootFileProvider { get; set; } } }

那麼你到底應該使用哪一個接口呢?最簡單的答案是"儘量使用IHostEnvironment接口"。

可是詳細來講,狀況有不少。。。

若是你正在編寫的ASP.NET Core 3.0的應用#

儘量是使用IHostEnviornment接口,但你須要訪問WebRootPathWebRootFileProvider兩個屬性的時候,請使用IWebHostEnvironment接口。

若是你正在編寫一個在通用主機和.NET Core 3.0項目中使用的類庫#

使用IHostEnvironment接口。你的類庫依然能夠在ASP.NET Core 3.0應用中可用。

若是你正在編寫一個在ASP.NET Core 3.0應用中使用的類庫#

和以前同樣,儘可能使用IHostEnvironment接口,由於你的類庫可能不只使用在ASP.NET Core應用中,還有可能使用在其餘通用主機應用中。然而,若是你須要訪問IWebHostEnvironment接口中的額外屬性,那麼你可能不得不更新你的類庫,讓它面向netcoreapp3.0,而不是netstandard2.0, 而且添加<FreameworkReference>元素配置。

若是你正在編寫一個在ASP.NET Core 2.x和3.0中使用的類庫#

這種場景比較難處理,基本上你有兩種可選的方案:

  • 你能夠繼續使用Microsoft.AspNetCore版本的IHostingEnvironment。它在2.x和3.0應用中均可以正常工做,你只須要在後續版本中中止使用便可。
  • 使用#ifdef條件編譯指令,針對ASP.NET Core 3.0使用IHostEnvironment接口,針對ASP.NET Core 2.x使用IHostingEnviornment接口。

IApplicationLifetime VS IHostApplicationLifetime#

IHostingEnvironment接口類似,IApplicationLifetime接口也有命名空間的衝突問題。和以前的例子相同,這兩個接口分別存在於Microsoft.Extensions.HostingMicrosoft.AspNetCore.Hosting中。可是在這個例子中,這兩個接口是徹底一致的。

 
 
 
 
 
 
Copy
// 與Microsoft.AspNetCore.Hosting中的定義徹底一致 namespace Microsoft.Extensions.Hosting { public interface IApplicationLifetime { CancellationToken ApplicationStarted { get; } CancellationToken ApplicationStopped { get; } CancellationToken ApplicationStopping { get; } void StopApplication(); } }

如你所料,這種重複是向後兼容的徵兆。在.NET Core 3.0中新的接口IHostApplicationLifetime被引入,該接口僅在Microsoft.Extensions.Hosting命名空間中定義,可是在通用主機和ASP.NET Core應用中均可以使用。

 
 
 
 
 
 
Copy
namespace Microsoft.Extensions.Hosting { public interface IHostApplicationLifetime { CancellationToken ApplicationStarted { get; } CancellationToken ApplicationStopping { get; } CancellationToken ApplicationStopped { get; } void StopApplication(); } }

一樣的,這個接口和以前版本是徹底一致的。ApplicationLifetime類型在通用主機項目的啓動和關閉中扮演了很是重要的角色。很是有趣的是,在Microsoft.AspNetCore.Hosting中沒有一個真正等價的類型,Extensions版本的接口處理了兩種不一樣的實現。AspNetCore命名空間中惟一的實現是一個簡單的封裝類,類型將實現委託給了一個做爲通用主機部分被添加的ApplicationLifetime對象中。

 
 
 
 
 
 
Copy
namespace Microsoft.AspNetCore.Hosting { internal class GenericWebHostApplicationLifetime : IApplicationLifetime { private readonly IHostApplicationLifetime _applicationLifetime; public GenericWebHostApplicationLifetime( IHostApplicationLifetime applicationLifetime) { _applicationLifetime = applicationLifetime; } public CancellationToken ApplicationStarted => _applicationLifetime.ApplicationStarted; public CancellationToken ApplicationStopping => _applicationLifetime.ApplicationStopping; public CancellationToken ApplicationStopped => _applicationLifetime.ApplicationStopped; public void StopApplication() => _applicationLifetime.StopApplication(); } }

幸運的是,選擇使用哪個接口,比選擇託管環境(Hosting Environment)要簡單的多。

若是你正在編寫一個.NET Core 3.0或者ASP.NET Core 3.0應用或者類庫#

使用IHostApplicationLifetime接口。你只須要引用Microsoft.Extensions.Hosting.Abstractions, 便可以在全部應用中使用。

若是你在編寫一個被ASP.NET Core 2.x和3.0應用共同使用的類庫#

如今,你可能又會陷入困境:

  • 你能夠繼續使用Microsoft.Extensions版本的IApplicationLifetime。它在2.x和3.0應用中均可以正常使用,可是在將來的版本中,你將不得不中止使用它
  • 使用#ifdef條件編譯指令,針對ASP.NET Core 3.0使用IHostApplicationLifetime接口,針對ASP.NET Core 2.x使用IApplicationLifetime接口。

幸運的是,IApplicationLifetime接口一般使用的比IHostingEnvironment接口少的多,因此你可能不會在此遇到過多的困難。

IWebHost VS IHost#

這裏有一件事情可能讓你驚訝,IWebHost接口沒有被更新,它沒有繼承ASP.NET Core 3.0中的IHost。類似的,IWebHostBuilder也沒有繼承自IHostBuilder。它們依然是徹底獨立的接口, 一個只工做在ASP.NET Core中,一個只工做在通用主機中。

幸運的是,這也沒有關係。如今ASP.NET Core 3.0已經被重構使用通用主機的抽象接口, 你能夠編寫使用通用主機IHostBuilder抽象的方法,並在ASP.NET Core和通用主機應用中共享它們。若是你須要進行ASP.NET Core的特定操做,你能夠依然使用IWebHostBuilder接口。

例如,你能夠編寫以下的擴展方法,一個使用IHostBuilder, 一個使用IWebHostBuilder:

 
 
 
 
 
 
Copy
public static class ExampleExtensions { public static IHostBuilder DoSomethingGeneric(this IHostBuilder builder) { // 添加通用主機配置 return builder; } public static IWebHostBuilder DoSomethingWeb(this IWebHostBuilder builder) { // 添加Web託管配置 return builder; } }

其中一個方法在通用主機上進行某些配置(列入,使用依賴注入註冊某些服務),在另一個方法中對IWebHostBuilder進行某種配置,例如你可能會爲Kestrel服務器設置一些默認值。

若是你在建立了一個全新的ASP.NET Core 3.0應用,你的Program.cs文件看起來應該是以下代碼:

 
 
 
 
 
 
Copy
public class Program { public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder .UseStartup<Startup>(); }); }

你能夠添加針對兩個擴展方法的調用。一個在通用IHostBuilder上調用,另外一個在ConfigWebHostDefaults()方法中,針對IWebHostBuilder調用

 
 
 
 
 
 
Copy
public class Program { public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .DoSomethingGeneric() // IHostBuilder擴展方法 .ConfigureWebHostDefaults(webBuilder => { webBuilder .DoSomethingWeb() // IWebHostBuilder擴展方法 .UseStartup<Startup>(); }); }

在ASP.NET Core 3.0中,你能夠對兩種構建器類型進行調用,這意味着,你如今能夠僅依賴通用主機的抽象,就能夠在ASP.NET Core應用中複用它們。而後,你能夠將ASP.NET Core的特性行爲放在頂層,而沒必要像2.x中同樣重複方法。

總結#

在本文中,咱們討論了ASP.NET Core 3.0中一些被標記爲廢棄的類型,它們被移動到哪裏去了,以及這麼作的緣由。若是你正在將一個應用升級到ASP.NET Core 3.0, 你並不須要立刻替換它們,由於他們如今的行爲依然相同,可是在未來的版本中會被替換掉,所以若是能夠的話,最好對其進行更新。在某些場景中,它還使你的應用之間共享代碼更加容易,所以值得研究一下。

相關文章
相關標籤/搜索