Skip to content
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
4 changes: 4 additions & 0 deletions eng/testing/linker/project.csproj.template
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
<_ExtraTrimmerArgs>{ExtraTrimmerArgs} $(_ExtraTrimmerArgs)</_ExtraTrimmerArgs>
</PropertyGroup>

<ItemGroup>
{AdditionalProjectReferences}
</ItemGroup>

<!-- Logic to override the default IlLink tasks that come from the SDK and use the one
we use in dotnet/runtime repo -->

Expand Down
12 changes: 11 additions & 1 deletion eng/testing/linker/trimmingTests.targets
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@
<_projectSourceFile>%(TestConsoleApps.ProjectCompileItems)</_projectSourceFile>
</PropertyGroup>

<ItemGroup Condition="'$(AdditionalProjectReferences)' != ''">
<_additionalProjectReferenceTemp Include="$(AdditionalProjectReferences)" />
<_additionalProjectReference Include="&lt;ProjectReference Include=&quot;$(LibrariesProjectRoot)%(_additionalProjectReferenceTemp.Identity)\src\%(_additionalProjectReferenceTemp.Identity).csproj&quot; SkipUseReferenceAssembly=&quot;true&quot; /&gt;" />
</ItemGroup>

<PropertyGroup>
<_additionalProjectReferencesString>@(_additionalProjectReference, '%0a')</_additionalProjectReferencesString>
</PropertyGroup>

<ItemGroup>
<_additionalProjectSourceFiles Include="%(TestConsoleApps.AdditionalSourceFiles)" />
</ItemGroup>
Expand All @@ -69,7 +78,8 @@
.Replace('{TargetingPackDir}','$(MicrosoftNetCoreAppRefPackDir)')
.Replace('{RuntimeIdentifier}','%(TestConsoleApps.TestRuntimeIdentifier)')
.Replace('{MicrosoftNETILLinkTasksVersion}', '$(MicrosoftNETILLinkTasksVersion)')
.Replace('{ExtraTrimmerArgs}', '%(TestConsoleApps.ExtraTrimmerArgs)'))"
.Replace('{ExtraTrimmerArgs}', '%(TestConsoleApps.ExtraTrimmerArgs)')
.Replace('{AdditionalProjectReferences}', '$(_additionalProjectReferencesString)'))"
Overwrite="true" />
<Copy SourceFiles="$(_projectSourceFile)"
DestinationFolder="$(_projectDir)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ static class ActivatorUtilities
/// <param name="instanceType">The type to activate</param>
/// <param name="parameters">Constructor arguments not provided by the <paramref name="provider"/>.</param>
/// <returns>An activated object of type instanceType</returns>
public static object CreateInstance(IServiceProvider provider, Type instanceType, params object[] parameters)
public static object CreateInstance(
IServiceProvider provider,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType,
params object[] parameters)
{
int bestLength = -1;
bool seenPreferred = false;
Expand All @@ -49,11 +52,9 @@ public static object CreateInstance(IServiceProvider provider, Type instanceType

if (!instanceType.GetTypeInfo().IsAbstract)
{
foreach (ConstructorInfo? constructor in instanceType
.GetTypeInfo()
.DeclaredConstructors)
foreach (ConstructorInfo? constructor in instanceType.GetConstructors())
{
if (!constructor.IsStatic && constructor.IsPublic)
if (!constructor.IsStatic)
{
var matcher = new ConstructorMatcher(constructor);
bool isPreferred = constructor.IsDefined(typeof(ActivatorUtilitiesConstructorAttribute), false);
Expand Down Expand Up @@ -104,7 +105,9 @@ public static object CreateInstance(IServiceProvider provider, Type instanceType
/// A factory that will instantiate instanceType using an <see cref="IServiceProvider"/>
/// and an argument array containing objects matching the types defined in argumentTypes
/// </returns>
public static ObjectFactory CreateFactory(Type instanceType, Type[] argumentTypes)
public static ObjectFactory CreateFactory(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType,
Type[] argumentTypes)
{
FindApplicableConstructor(instanceType, argumentTypes, out ConstructorInfo? constructor, out int?[]? parameterMap);

Expand All @@ -126,19 +129,18 @@ public static ObjectFactory CreateFactory(Type instanceType, Type[] argumentType
/// <param name="provider">The service provider used to resolve dependencies</param>
/// <param name="parameters">Constructor arguments not provided by the <paramref name="provider"/>.</param>
/// <returns>An activated object of type T</returns>
public static T CreateInstance<T>(IServiceProvider provider, params object[] parameters)
public static T CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(IServiceProvider provider, params object[] parameters)
{
return (T)CreateInstance(provider, typeof(T), parameters);
}


/// <summary>
/// Retrieve an instance of the given type from the service provider. If one is not found then instantiate it directly.
/// </summary>
/// <typeparam name="T">The type of the service</typeparam>
/// <param name="provider">The service provider used to resolve dependencies</param>
/// <returns>The resolved service or created instance</returns>
public static T GetServiceOrCreateInstance<T>(IServiceProvider provider)
public static T GetServiceOrCreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(IServiceProvider provider)
{
return (T)GetServiceOrCreateInstance(provider, typeof(T));
}
Expand All @@ -149,7 +151,9 @@ public static T GetServiceOrCreateInstance<T>(IServiceProvider provider)
/// <param name="provider">The service provider</param>
/// <param name="type">The type of the service</param>
/// <returns>The resolved service or created instance</returns>
public static object GetServiceOrCreateInstance(IServiceProvider provider, Type type)
public static object GetServiceOrCreateInstance(
IServiceProvider provider,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type type)
{
return provider.GetService(type) ?? CreateInstance(provider, type);
}
Expand Down Expand Up @@ -214,7 +218,7 @@ private static Expression BuildFactoryExpression(
}

private static void FindApplicableConstructor(
Type instanceType,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType,
Type[] argumentTypes,
out ConstructorInfo matchingConstructor,
out int?[] matchingParameterMap)
Expand All @@ -235,14 +239,14 @@ private static void FindApplicableConstructor(

// Tries to find constructor based on provided argument types
private static bool TryFindMatchingConstructor(
Type instanceType,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType,
Type[] argumentTypes,
[NotNullWhen(true)] ref ConstructorInfo? matchingConstructor,
[NotNullWhen(true)] ref int?[]? parameterMap)
{
foreach (ConstructorInfo? constructor in instanceType.GetTypeInfo().DeclaredConstructors)
foreach (ConstructorInfo? constructor in instanceType.GetConstructors())
{
if (constructor.IsStatic || !constructor.IsPublic)
if (constructor.IsStatic)
{
continue;
}
Expand Down Expand Up @@ -270,15 +274,15 @@ private static bool TryFindMatchingConstructor(

// Tries to find constructor marked with ActivatorUtilitiesConstructorAttribute
private static bool TryFindPreferredConstructor(
Type instanceType,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type instanceType,
Type[] argumentTypes,
[NotNullWhen(true)] ref ConstructorInfo? matchingConstructor,
[NotNullWhen(true)] ref int?[]? parameterMap)
{
bool seenPreferred = false;
foreach (ConstructorInfo? constructor in instanceType.GetTypeInfo().DeclaredConstructors)
foreach (ConstructorInfo? constructor in instanceType.GetConstructors())
{
if (constructor.IsStatic || !constructor.IsPublic)
if (constructor.IsStatic)
{
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#nullable enable

using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace Microsoft.Extensions.Internal
Expand Down Expand Up @@ -41,9 +42,13 @@ public static bool TryGetDefaultValue(ParameterInfo parameter, out object? defau
// Workaround for https://github.com/dotnet/corefx/issues/11797
if (defaultValue == null && parameter.ParameterType.IsValueType)
{
defaultValue = Activator.CreateInstance(parameter.ParameterType);
defaultValue = CreateValueType(parameter.ParameterType);
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "CreateInstance is only called on a ValueType, which will always have a default constructor.")]
object? CreateValueType(Type t) => Activator.CreateInstance(t);

// Handle nullable enums
if (defaultValue != null &&
parameter.ParameterType.IsGenericType &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

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

namespace Microsoft.Extensions.DependencyInjection.Extensions
Expand Down Expand Up @@ -124,7 +125,7 @@ public static void TryAdd(
/// <param name="service">The type of the service to register.</param>
public static void TryAddTransient(
this IServiceCollection collection,
Type service)
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service)
{
if (collection == null)
{
Expand All @@ -151,7 +152,7 @@ public static void TryAddTransient(
public static void TryAddTransient(
this IServiceCollection collection,
Type service,
Type implementationType)
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
{
if (collection == null)
{
Expand Down Expand Up @@ -210,7 +211,7 @@ public static void TryAddTransient(
/// </summary>
/// <typeparam name="TService">The type of the service to add.</typeparam>
/// <param name="collection">The <see cref="IServiceCollection"/>.</param>
public static void TryAddTransient<TService>(this IServiceCollection collection)
public static void TryAddTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection)
where TService : class
{
if (collection == null)
Expand All @@ -229,7 +230,7 @@ public static void TryAddTransient<TService>(this IServiceCollection collection)
/// <typeparam name="TService">The type of the service to add.</typeparam>
/// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
/// <param name="collection">The <see cref="IServiceCollection"/>.</param>
public static void TryAddTransient<TService, TImplementation>(this IServiceCollection collection)
public static void TryAddTransient<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection collection)
where TService : class
where TImplementation : class, TService
{
Expand Down Expand Up @@ -265,7 +266,7 @@ public static void TryAddTransient<TService>(
/// <param name="service">The type of the service to register.</param>
public static void TryAddScoped(
this IServiceCollection collection,
Type service)
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service)
{
if (collection == null)
{
Expand All @@ -292,7 +293,7 @@ public static void TryAddScoped(
public static void TryAddScoped(
this IServiceCollection collection,
Type service,
Type implementationType)
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
{
if (collection == null)
{
Expand Down Expand Up @@ -351,7 +352,7 @@ public static void TryAddScoped(
/// </summary>
/// <typeparam name="TService">The type of the service to add.</typeparam>
/// <param name="collection">The <see cref="IServiceCollection"/>.</param>
public static void TryAddScoped<TService>(this IServiceCollection collection)
public static void TryAddScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection)
where TService : class
{
if (collection == null)
Expand All @@ -370,7 +371,7 @@ public static void TryAddScoped<TService>(this IServiceCollection collection)
/// <typeparam name="TService">The type of the service to add.</typeparam>
/// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
/// <param name="collection">The <see cref="IServiceCollection"/>.</param>
public static void TryAddScoped<TService, TImplementation>(this IServiceCollection collection)
public static void TryAddScoped<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection collection)
where TService : class
where TImplementation : class, TService
{
Expand Down Expand Up @@ -406,7 +407,7 @@ public static void TryAddScoped<TService>(
/// <param name="service">The type of the service to register.</param>
public static void TryAddSingleton(
this IServiceCollection collection,
Type service)
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service)
{
if (collection == null)
{
Expand All @@ -433,7 +434,7 @@ public static void TryAddSingleton(
public static void TryAddSingleton(
this IServiceCollection collection,
Type service,
Type implementationType)
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType)
{
if (collection == null)
{
Expand Down Expand Up @@ -492,7 +493,7 @@ public static void TryAddSingleton(
/// </summary>
/// <typeparam name="TService">The type of the service to add.</typeparam>
/// <param name="collection">The <see cref="IServiceCollection"/>.</param>
public static void TryAddSingleton<TService>(this IServiceCollection collection)
public static void TryAddSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection)
where TService : class
{
if (collection == null)
Expand All @@ -511,7 +512,7 @@ public static void TryAddSingleton<TService>(this IServiceCollection collection)
/// <typeparam name="TService">The type of the service to add.</typeparam>
/// <typeparam name="TImplementation">The type of the implementation to use.</typeparam>
/// <param name="collection">The <see cref="IServiceCollection"/>.</param>
public static void TryAddSingleton<TService, TImplementation>(this IServiceCollection collection)
public static void TryAddSingleton<TService, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TImplementation>(this IServiceCollection collection)
where TService : class
where TImplementation : class, TService
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
Link="Common\src\Extensions\ActivatorUtilities\ActivatorUtilitiesConstructorAttribute.cs" />
<Compile Include="$(CommonPath)Extensions\ActivatorUtilities\ObjectFactory.cs"
Link="Common\src\Extensions\ActivatorUtilities\ObjectFactory.cs" />
<Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\DynamicallyAccessedMembersAttribute.cs" />
<Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\DynamicallyAccessedMemberTypes.cs" />
<Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\UnconditionalSuppressMessageAttribute.cs" />
</ItemGroup>

</Project>
Loading