diff --git a/src/libraries/Common/src/Extensions/ActivatorUtilities/ActivatorUtilities.cs b/src/libraries/Common/src/Extensions/ActivatorUtilities/ActivatorUtilities.cs index c4c20f1fba3b40..2c397dcd075211 100644 --- a/src/libraries/Common/src/Extensions/ActivatorUtilities/ActivatorUtilities.cs +++ b/src/libraries/Common/src/Extensions/ActivatorUtilities/ActivatorUtilities.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -30,7 +32,7 @@ namespace Microsoft.Extensions.Internal static class ActivatorUtilities { private static readonly MethodInfo GetServiceInfo = - GetMethodInfo>((sp, t, r, c) => GetService(sp, t, r, c)); + GetMethodInfo>((sp, t, r, c) => GetService(sp, t, r, c)); /// /// Instantiate a type with constructor arguments provided directly and/or from an . @@ -105,7 +107,7 @@ public static object CreateInstance(IServiceProvider provider, Type instanceType /// public static ObjectFactory CreateFactory(Type instanceType, Type[] argumentTypes) { - FindApplicableConstructor(instanceType, argumentTypes, out ConstructorInfo constructor, out int?[] parameterMap); + FindApplicableConstructor(instanceType, argumentTypes, out ConstructorInfo? constructor, out int?[]? parameterMap); var provider = Expression.Parameter(typeof(IServiceProvider), "provider"); var argumentArray = Expression.Parameter(typeof(object[]), "argumentArray"); @@ -159,7 +161,7 @@ private static MethodInfo GetMethodInfo(Expression expr) return mc.Method; } - private static object GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired) + private static object? GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired) { var service = sp.GetService(type); if (service == null && !isDefaultParameterRequired) @@ -216,25 +218,28 @@ private static void FindApplicableConstructor( Type instanceType, Type[] argumentTypes, out ConstructorInfo matchingConstructor, - out int?[] parameterMap) + out int?[] matchingParameterMap) { - matchingConstructor = null; - parameterMap = null; + ConstructorInfo? constructorInfo = null; + int?[]? parameterMap = null; - if (!TryFindPreferredConstructor(instanceType, argumentTypes, ref matchingConstructor, ref parameterMap) && - !TryFindMatchingConstructor(instanceType, argumentTypes, ref matchingConstructor, ref parameterMap)) + if (!TryFindPreferredConstructor(instanceType, argumentTypes, ref constructorInfo, ref parameterMap) && + !TryFindMatchingConstructor(instanceType, argumentTypes, ref constructorInfo, ref parameterMap)) { var message = $"A suitable constructor for type '{instanceType}' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor."; throw new InvalidOperationException(message); } + + matchingConstructor = constructorInfo; + matchingParameterMap = parameterMap; } // Tries to find constructor based on provided argument types private static bool TryFindMatchingConstructor( Type instanceType, Type[] argumentTypes, - ref ConstructorInfo matchingConstructor, - ref int?[] parameterMap) + [NotNullWhen(true)] ref ConstructorInfo? matchingConstructor, + [NotNullWhen(true)] ref int?[]? parameterMap) { foreach (var constructor in instanceType.GetTypeInfo().DeclaredConstructors) { @@ -255,15 +260,21 @@ private static bool TryFindMatchingConstructor( } } - return matchingConstructor != null; + if (matchingConstructor != null) + { + Debug.Assert(parameterMap != null); + return true; + } + + return false; } // Tries to find constructor marked with ActivatorUtilitiesConstructorAttribute private static bool TryFindPreferredConstructor( Type instanceType, Type[] argumentTypes, - ref ConstructorInfo matchingConstructor, - ref int?[] parameterMap) + [NotNullWhen(true)] ref ConstructorInfo? matchingConstructor, + [NotNullWhen(true)] ref int?[]? parameterMap) { var seenPreferred = false; foreach (var constructor in instanceType.GetTypeInfo().DeclaredConstructors) @@ -291,7 +302,13 @@ private static bool TryFindPreferredConstructor( } } - return matchingConstructor != null; + if (matchingConstructor != null) + { + Debug.Assert(parameterMap != null); + return true; + } + + return false; } // Creates an injective parameterMap from givenParameterTypes to assignable constructorParameters. @@ -334,13 +351,13 @@ private struct ConstructorMatcher { private readonly ConstructorInfo _constructor; private readonly ParameterInfo[] _parameters; - private readonly object[] _parameterValues; + private readonly object?[] _parameterValues; public ConstructorMatcher(ConstructorInfo constructor) { _constructor = constructor; _parameters = _constructor.GetParameters(); - _parameterValues = new object[_parameters.Length]; + _parameterValues = new object?[_parameters.Length]; } public int Match(object[] givenParameters) diff --git a/src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.cs b/src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.cs index c55b7a3cb7fca9..abcbf454dcfa5a 100644 --- a/src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.cs +++ b/src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.Reflection; @@ -11,7 +13,7 @@ internal class ParameterDefaultValue { private static readonly Type _nullable = typeof(Nullable<>); - public static bool TryGetDefaultValue(ParameterInfo parameter, out object defaultValue) + public static bool TryGetDefaultValue(ParameterInfo parameter, out object? defaultValue) { bool hasDefaultValue; var tryToGetDefaultValue = true; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs index 733838e7e5f223..aac4f5d2c027d5 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -22,7 +22,7 @@ public ActivatorUtilitiesConstructorAttribute() { } public partial interface IServiceCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { } - public partial interface IServiceProviderFactory + public partial interface IServiceProviderFactory where TContainerBuilder : notnull { TContainerBuilder CreateBuilder(Microsoft.Extensions.DependencyInjection.IServiceCollection services); System.IServiceProvider CreateServiceProvider(TContainerBuilder containerBuilder); @@ -71,9 +71,9 @@ public partial class ServiceDescriptor public ServiceDescriptor(System.Type serviceType, System.Func factory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } public ServiceDescriptor(System.Type serviceType, object instance) { } public ServiceDescriptor(System.Type serviceType, System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { } - public System.Func ImplementationFactory { get { throw null; } } - public object ImplementationInstance { get { throw null; } } - public System.Type ImplementationType { get { throw null; } } + public System.Func? ImplementationFactory { get { throw null; } } + public object? ImplementationInstance { get { throw null; } } + public System.Type? ImplementationType { get { throw null; } } public Microsoft.Extensions.DependencyInjection.ServiceLifetime Lifetime { get { throw null; } } public System.Type ServiceType { get { throw null; } } public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; } @@ -107,9 +107,10 @@ public static partial class ServiceProviderServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceScope CreateScope(this System.IServiceProvider provider) { throw null; } public static object GetRequiredService(this System.IServiceProvider provider, System.Type serviceType) { throw null; } - public static T GetRequiredService(this System.IServiceProvider provider) { throw null; } - public static System.Collections.Generic.IEnumerable GetServices(this System.IServiceProvider provider, System.Type serviceType) { throw null; } + public static T GetRequiredService(this System.IServiceProvider provider) where T : notnull { throw null; } + public static System.Collections.Generic.IEnumerable GetServices(this System.IServiceProvider provider, System.Type serviceType) { throw null; } public static System.Collections.Generic.IEnumerable GetServices(this System.IServiceProvider provider) { throw null; } + [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute] public static T GetService(this System.IServiceProvider provider) { throw null; } } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.csproj index 0adff566b0bfd4..942dbe0ee15295 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/ref/Microsoft.Extensions.DependencyInjection.Abstractions.csproj @@ -1,6 +1,7 @@ netstandard2.0 + enable diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderFactory.cs index 0d0a66bab676ab..a8b71bce3db761 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/IServiceProviderFactory.cs @@ -9,7 +9,7 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Provides an extension point for creating a container specific builder and an . /// - public interface IServiceProviderFactory + public interface IServiceProviderFactory where TContainerBuilder : notnull { /// /// Creates a container builder from an . diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj index 167a6ebd19e972..17654fa1889d07 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj @@ -4,6 +4,7 @@ netstandard2.0 $(DefineConstants);ActivatorUtilities_In_DependencyInjection true + enable diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index bb850efe12facd..409aa6da34af5e 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -100,13 +100,13 @@ private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime) public Type ServiceType { get; } /// - public Type ImplementationType { get; } + public Type? ImplementationType { get; } /// - public object ImplementationInstance { get; } + public object? ImplementationInstance { get; } /// - public Func ImplementationFactory { get; } + public Func? ImplementationFactory { get; } /// public override string ToString() diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs index 1a7ffad12ad7d8..830009056e57ac 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.DependencyInjection { @@ -18,6 +19,7 @@ public static class ServiceProviderServiceExtensions /// The type of service object to get. /// The to retrieve the service object from. /// A service object of type or null if there is no such service. + [return: MaybeNull] public static T GetService(this IServiceProvider provider) { if (provider == null) @@ -69,7 +71,7 @@ public static object GetRequiredService(this IServiceProvider provider, Type ser /// The to retrieve the service object from. /// A service object of type . /// There is no service of type . - public static T GetRequiredService(this IServiceProvider provider) + public static T GetRequiredService(this IServiceProvider provider) where T : notnull { if (provider == null) { @@ -101,7 +103,7 @@ public static IEnumerable GetServices(this IServiceProvider provider) /// The to retrieve the services from. /// An object that specifies the type of service object to get. /// An enumeration of services of type . - public static IEnumerable GetServices(this IServiceProvider provider, Type serviceType) + public static IEnumerable GetServices(this IServiceProvider provider, Type serviceType) { if (provider == null) {