例如,ASP.NET Core的实现类如下:
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接口,但你需要访问WebRootPath和WebRootFileProvider两个属性的时候,请使用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.Hosting和Microsoft.AspNetCore.Hosting中。但是在这个例子中,这两个接口是完全一致的。
// 与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应用中都可以使用。
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对象中。
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