Skip to content

Annotate Microsoft.Extensions.DependencyInjection.Abstractions for nu… #37488

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

Merged
merged 5 commits into from
Jun 16, 2020
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 @@ -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;
Expand Down Expand Up @@ -30,7 +32,7 @@ namespace Microsoft.Extensions.Internal
static class ActivatorUtilities
{
private static readonly MethodInfo GetServiceInfo =
GetMethodInfo<Func<IServiceProvider, Type, Type, bool, object>>((sp, t, r, c) => GetService(sp, t, r, c));
GetMethodInfo<Func<IServiceProvider, Type, Type, bool, object?>>((sp, t, r, c) => GetService(sp, t, r, c));

/// <summary>
/// Instantiate a type with constructor arguments provided directly and/or from an <see cref="IServiceProvider"/>.
Expand Down Expand Up @@ -105,7 +107,7 @@ public static object CreateInstance(IServiceProvider provider, Type instanceType
/// </returns>
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");
Expand Down Expand Up @@ -159,7 +161,7 @@ private static MethodInfo GetMethodInfo<T>(Expression<T> 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)
Expand Down Expand Up @@ -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)
{
Expand All @@ -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)
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

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

Do you need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a shared source file. So you have to annotate it in case other projects that reference it haven't been updated to nullable.


using System;
using System.Reflection;

Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public ActivatorUtilitiesConstructorAttribute() { }
public partial interface IServiceCollection : System.Collections.Generic.ICollection<Microsoft.Extensions.DependencyInjection.ServiceDescriptor>, System.Collections.Generic.IEnumerable<Microsoft.Extensions.DependencyInjection.ServiceDescriptor>, System.Collections.Generic.IList<Microsoft.Extensions.DependencyInjection.ServiceDescriptor>, System.Collections.IEnumerable
{
}
public partial interface IServiceProviderFactory<TContainerBuilder>
public partial interface IServiceProviderFactory<TContainerBuilder> where TContainerBuilder : notnull
{
TContainerBuilder CreateBuilder(Microsoft.Extensions.DependencyInjection.IServiceCollection services);
System.IServiceProvider CreateServiceProvider(TContainerBuilder containerBuilder);
Expand Down Expand Up @@ -71,9 +71,9 @@ public partial class ServiceDescriptor
public ServiceDescriptor(System.Type serviceType, System.Func<System.IServiceProvider, object> 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<System.IServiceProvider, object> ImplementationFactory { get { throw null; } }
public object ImplementationInstance { get { throw null; } }
public System.Type ImplementationType { get { throw null; } }
public System.Func<System.IServiceProvider, object>? 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<System.IServiceProvider, object> implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) { throw null; }
Expand Down Expand Up @@ -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<T>(this System.IServiceProvider provider) { throw null; }
public static System.Collections.Generic.IEnumerable<object> GetServices(this System.IServiceProvider provider, System.Type serviceType) { throw null; }
public static T GetRequiredService<T>(this System.IServiceProvider provider) where T : notnull { throw null; }
public static System.Collections.Generic.IEnumerable<object?> GetServices(this System.IServiceProvider provider, System.Type serviceType) { throw null; }
public static System.Collections.Generic.IEnumerable<T> GetServices<T>(this System.IServiceProvider provider) { throw null; }
[return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
public static T GetService<T>(this System.IServiceProvider provider) { throw null; }
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="Microsoft.Extensions.DependencyInjection.Abstractions.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <summary>
/// Provides an extension point for creating a container specific builder and an <see cref="IServiceProvider"/>.
/// </summary>
public interface IServiceProviderFactory<TContainerBuilder>
public interface IServiceProviderFactory<TContainerBuilder> where TContainerBuilder : notnull
{
/// <summary>
/// Creates a container builder from an <see cref="IServiceCollection"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<DefineConstants>$(DefineConstants);ActivatorUtilities_In_DependencyInjection</DefineConstants>
<EnableDefaultItems>true</EnableDefaultItems>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,13 @@ private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime)
public Type ServiceType { get; }

/// <inheritdoc />
public Type ImplementationType { get; }
public Type? ImplementationType { get; }

/// <inheritdoc />
public object ImplementationInstance { get; }
public object? ImplementationInstance { get; }

/// <inheritdoc />
public Func<IServiceProvider, object> ImplementationFactory { get; }
public Func<IServiceProvider, object>? ImplementationFactory { get; }

/// <inheritdoc />
public override string ToString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.Extensions.DependencyInjection
{
Expand All @@ -18,6 +19,7 @@ public static class ServiceProviderServiceExtensions
/// <typeparam name="T">The type of service object to get.</typeparam>
/// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the service object from.</param>
/// <returns>A service object of type <typeparamref name="T"/> or null if there is no such service.</returns>
[return: MaybeNull]
public static T GetService<T>(this IServiceProvider provider)
{
if (provider == null)
Expand Down Expand Up @@ -69,7 +71,7 @@ public static object GetRequiredService(this IServiceProvider provider, Type ser
/// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the service object from.</param>
/// <returns>A service object of type <typeparamref name="T"/>.</returns>
/// <exception cref="System.InvalidOperationException">There is no service of type <typeparamref name="T"/>.</exception>
public static T GetRequiredService<T>(this IServiceProvider provider)
public static T GetRequiredService<T>(this IServiceProvider provider) where T : notnull
{
if (provider == null)
{
Expand Down Expand Up @@ -101,7 +103,7 @@ public static IEnumerable<T> GetServices<T>(this IServiceProvider provider)
/// <param name="provider">The <see cref="IServiceProvider"/> to retrieve the services from.</param>
/// <param name="serviceType">An object that specifies the type of service object to get.</param>
/// <returns>An enumeration of services of type <paramref name="serviceType"/>.</returns>
public static IEnumerable<object> GetServices(this IServiceProvider provider, Type serviceType)
public static IEnumerable<object?> GetServices(this IServiceProvider provider, Type serviceType)
{
if (provider == null)
{
Expand Down