Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Group 3] Enable nullable annotations for Microsoft.Extensions.Hosting.Abstractions #65403

Merged
merged 8 commits into from
Mar 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace Microsoft.Extensions.Hosting
public abstract partial class BackgroundService : Microsoft.Extensions.Hosting.IHostedService, System.IDisposable
{
protected BackgroundService() { }
public virtual System.Threading.Tasks.Task ExecuteTask { get { throw null; } }
public virtual System.Threading.Tasks.Task? ExecuteTask { get { throw null; } }
public virtual void Dispose() { }
protected abstract System.Threading.Tasks.Task ExecuteAsync(System.Threading.CancellationToken stoppingToken);
public virtual System.Threading.Tasks.Task StartAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
Expand Down Expand Up @@ -106,8 +106,8 @@ public partial interface IHostBuilder
Microsoft.Extensions.Hosting.IHostBuilder ConfigureContainer<TContainerBuilder>(System.Action<Microsoft.Extensions.Hosting.HostBuilderContext, TContainerBuilder> configureDelegate);
Microsoft.Extensions.Hosting.IHostBuilder ConfigureHostConfiguration(System.Action<Microsoft.Extensions.Configuration.IConfigurationBuilder> configureDelegate);
Microsoft.Extensions.Hosting.IHostBuilder ConfigureServices(System.Action<Microsoft.Extensions.Hosting.HostBuilderContext, Microsoft.Extensions.DependencyInjection.IServiceCollection> configureDelegate);
Microsoft.Extensions.Hosting.IHostBuilder UseServiceProviderFactory<TContainerBuilder>(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder> factory);
Microsoft.Extensions.Hosting.IHostBuilder UseServiceProviderFactory<TContainerBuilder>(System.Func<Microsoft.Extensions.Hosting.HostBuilderContext, Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder>> factory);
Microsoft.Extensions.Hosting.IHostBuilder UseServiceProviderFactory<TContainerBuilder>(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder> factory) where TContainerBuilder : notnull;
Microsoft.Extensions.Hosting.IHostBuilder UseServiceProviderFactory<TContainerBuilder>(System.Func<Microsoft.Extensions.Hosting.HostBuilderContext, Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<TContainerBuilder>> factory) where TContainerBuilder : notnull;
}
public partial interface IHostedService
{
Expand All @@ -116,15 +116,15 @@ public partial interface IHostedService
}
public partial interface IHostEnvironment
{
string ApplicationName { get; set; }
string? ApplicationName { get; set; }
Microsoft.Extensions.FileProviders.IFileProvider ContentRootFileProvider { get; set; }
string ContentRootPath { get; set; }
Comment on lines 120 to 121
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will probably have problems with these two in the Hosting PR, but we can deal with it then. I think the intention here is that these two properties are not null.

string EnvironmentName { get; set; }
}
[System.ObsoleteAttribute("IHostingEnvironment has been deprecated. Use Microsoft.Extensions.Hosting.IHostEnvironment instead.")]
public partial interface IHostingEnvironment
{
string ApplicationName { get; set; }
string? ApplicationName { get; set; }
Microsoft.Extensions.FileProviders.IFileProvider ContentRootFileProvider { get; set; }
string ContentRootPath { get; set; }
string EnvironmentName { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);CS0618</NoWarn>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ namespace Microsoft.Extensions.Hosting
/// </summary>
public abstract class BackgroundService : IHostedService, IDisposable
{
private Task _executeTask;
private CancellationTokenSource _stoppingCts;
private Task? _executeTask;
private CancellationTokenSource? _stoppingCts;

/// <summary>
/// Gets the Task that executes the background operation.
/// </summary>
/// <remarks>
/// Will return <see langword="null"/> if the background operation hasn't started.
/// </remarks>
public virtual Task ExecuteTask => _executeTask;
public virtual Task? ExecuteTask => _executeTask;
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// This method is called when the <see cref="IHostedService"/> starts. The implementation should return a task that represents
Expand Down Expand Up @@ -69,7 +69,7 @@ public virtual async Task StopAsync(CancellationToken cancellationToken)
try
{
// Signal cancellation to the executing method
_stoppingCts.Cancel();
_stoppingCts!.Cancel();
}
finally
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public HostBuilderContext(IDictionary<object, object> properties!!)
/// <summary>
/// The <see cref="IHostEnvironment" /> initialized by the <see cref="IHost" />.
/// </summary>
public IHostEnvironment HostingEnvironment { get; set; }
public IHostEnvironment HostingEnvironment { get; set; } = null!;

/// <summary>
/// The <see cref="IConfiguration" /> containing the merged configuration of the application and the <see cref="IHost" />.
/// </summary>
public IConfiguration Configuration { get; set; }
public IConfiguration Configuration { get; set; } = null!;

/// <summary>
/// A central location for sharing state between components during the host building process.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,18 @@ public static async Task RunAsync(this IHost host, CancellationToken token = def
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public static async Task WaitForShutdownAsync(this IHost host, CancellationToken token = default)
{
IHostApplicationLifetime applicationLifetime = host.Services.GetService<IHostApplicationLifetime>();
IHostApplicationLifetime applicationLifetime = host.Services.GetRequiredService<IHostApplicationLifetime>();
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved

token.Register(state =>
{
((IHostApplicationLifetime)state).StopApplication();
((IHostApplicationLifetime)state!).StopApplication();
},
applicationLifetime);

var waitForStop = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
var waitForStop = new TaskCompletionSource<object?>(TaskCreationOptions.RunContinuationsAsynchronously);
applicationLifetime.ApplicationStopping.Register(obj =>
{
var tcs = (TaskCompletionSource<object>)obj;
var tcs = (TaskCompletionSource<object?>)obj!;
maxkoshevoi marked this conversation as resolved.
Show resolved Hide resolved
tcs.TrySetResult(null);
}, waitForStop);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ public interface IHostBuilder
/// <typeparam name="TContainerBuilder">The type of builder.</typeparam>
/// <param name="factory">The factory to register.</param>
/// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns>
IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory);
IHostBuilder UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory) where TContainerBuilder : notnull;

/// <summary>
/// Overrides the factory used to create the service provider.
/// </summary>
/// <typeparam name="TContainerBuilder">The type of builder.</typeparam>
/// <returns>The same instance of the <see cref="IHostBuilder"/> for chaining.</returns>
IHostBuilder UseServiceProviderFactory<TContainerBuilder>(Func<HostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factory);
IHostBuilder UseServiceProviderFactory<TContainerBuilder>(Func<HostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factory) where TContainerBuilder : notnull;

/// <summary>
/// Enables configuring the instantiated dependency container. This can be called multiple times and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public interface IHostEnvironment
/// Gets or sets the name of the application. This property is automatically set by the host to the assembly containing
/// the application entry point.
/// </summary>
string ApplicationName { get; set; }
string? ApplicationName { get; set; }

/// <summary>
/// Gets or sets the absolute path to the directory that contains the application content files.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public interface IHostingEnvironment
/// Gets or sets the name of the application. This property is automatically set by the host to the assembly containing
/// the application entry point.
/// </summary>
string ApplicationName { get; set; }
string? ApplicationName { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eerhardt This one seems odd to be nullable, similar to EnvironmentName above, this is set automatically by the host

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the current code, this annotation is correct as there are scenarios where it can be null:

var hostingEnvironment = new HostingEnvironment()
{
ApplicationName = hostConfiguration[HostDefaults.ApplicationKey],
EnvironmentName = hostConfiguration[HostDefaults.EnvironmentKey] ?? Environments.Production,
ContentRootPath = ResolveContentRootPath(hostConfiguration[HostDefaults.ContentRootKey], AppContext.BaseDirectory),
};
if (string.IsNullOrEmpty(hostingEnvironment.ApplicationName))
{
// Note GetEntryAssembly returns null for the net4x console test runner.
hostingEnvironment.ApplicationName = Assembly.GetEntryAssembly()?.GetName().Name;
}


/// <summary>
/// Gets or sets the absolute path to the directory that contains the application content files.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
<Nullable>enable</Nullable>
<RootNamespace>Microsoft.Extensions.Hosting</RootNamespace>
<EnableDefaultItems>true</EnableDefaultItems>
<!-- Use targeting pack references instead of granular ones in the project file. -->
Expand Down