diff --git a/eng/testing/linker/project.csproj.template b/eng/testing/linker/project.csproj.template index ef63096e8019c0..64a3e93967a3de 100644 --- a/eng/testing/linker/project.csproj.template +++ b/eng/testing/linker/project.csproj.template @@ -9,6 +9,10 @@ <_ExtraTrimmerArgs>{ExtraTrimmerArgs} $(_ExtraTrimmerArgs) + + {AdditionalProjectReferences} + + diff --git a/eng/testing/linker/trimmingTests.targets b/eng/testing/linker/trimmingTests.targets index 3729bd306bca94..6d89002d9e0c6a 100644 --- a/eng/testing/linker/trimmingTests.targets +++ b/eng/testing/linker/trimmingTests.targets @@ -57,6 +57,15 @@ <_projectSourceFile>%(TestConsoleApps.ProjectCompileItems) + + <_additionalProjectReferenceTemp Include="$(AdditionalProjectReferences)" /> + <_additionalProjectReference Include="<ProjectReference Include="$(LibrariesProjectRoot)%(_additionalProjectReferenceTemp.Identity)\src\%(_additionalProjectReferenceTemp.Identity).csproj" SkipUseReferenceAssembly="true" />" /> + + + + <_additionalProjectReferencesString>@(_additionalProjectReference, '%0a') + + <_additionalProjectSourceFiles Include="%(TestConsoleApps.AdditionalSourceFiles)" /> @@ -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" /> diff --git a/src/libraries/Common/src/Extensions/ActivatorUtilities/ActivatorUtilities.cs b/src/libraries/Common/src/Extensions/ActivatorUtilities/ActivatorUtilities.cs index 7f5b6c3aa0a529..574fd893febaae 100644 --- a/src/libraries/Common/src/Extensions/ActivatorUtilities/ActivatorUtilities.cs +++ b/src/libraries/Common/src/Extensions/ActivatorUtilities/ActivatorUtilities.cs @@ -40,7 +40,10 @@ static class ActivatorUtilities /// The type to activate /// Constructor arguments not provided by the . /// An activated object of type instanceType - 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; @@ -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); @@ -104,7 +105,9 @@ public static object CreateInstance(IServiceProvider provider, Type instanceType /// A factory that will instantiate instanceType using an /// and an argument array containing objects matching the types defined in argumentTypes /// - 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); @@ -126,19 +129,18 @@ public static ObjectFactory CreateFactory(Type instanceType, Type[] argumentType /// The service provider used to resolve dependencies /// Constructor arguments not provided by the . /// An activated object of type T - public static T CreateInstance(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); } - /// /// Retrieve an instance of the given type from the service provider. If one is not found then instantiate it directly. /// /// The type of the service /// The service provider used to resolve dependencies /// The resolved service or created instance - public static T GetServiceOrCreateInstance(IServiceProvider provider) + public static T GetServiceOrCreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(IServiceProvider provider) { return (T)GetServiceOrCreateInstance(provider, typeof(T)); } @@ -149,7 +151,9 @@ public static T GetServiceOrCreateInstance(IServiceProvider provider) /// The service provider /// The type of the service /// The resolved service or created instance - 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); } @@ -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) @@ -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; } @@ -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; } diff --git a/src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.cs b/src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.cs index 03f1b26ec0e233..45e8a6aea1d0b7 100644 --- a/src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.cs +++ b/src/libraries/Common/src/Extensions/ParameterDefaultValue/ParameterDefaultValue.cs @@ -4,6 +4,7 @@ #nullable enable using System; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace Microsoft.Extensions.Internal @@ -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 && diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs index ad5be9396bf955..b1d8704fe0cbad 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace Microsoft.Extensions.DependencyInjection.Extensions @@ -124,7 +125,7 @@ public static void TryAdd( /// The type of the service to register. public static void TryAddTransient( this IServiceCollection collection, - Type service) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service) { if (collection == null) { @@ -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) { @@ -210,7 +211,7 @@ public static void TryAddTransient( /// /// The type of the service to add. /// The . - public static void TryAddTransient(this IServiceCollection collection) + public static void TryAddTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection) where TService : class { if (collection == null) @@ -229,7 +230,7 @@ public static void TryAddTransient(this IServiceCollection collection) /// The type of the service to add. /// The type of the implementation to use. /// The . - public static void TryAddTransient(this IServiceCollection collection) + public static void TryAddTransient(this IServiceCollection collection) where TService : class where TImplementation : class, TService { @@ -265,7 +266,7 @@ public static void TryAddTransient( /// The type of the service to register. public static void TryAddScoped( this IServiceCollection collection, - Type service) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service) { if (collection == null) { @@ -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) { @@ -351,7 +352,7 @@ public static void TryAddScoped( /// /// The type of the service to add. /// The . - public static void TryAddScoped(this IServiceCollection collection) + public static void TryAddScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection) where TService : class { if (collection == null) @@ -370,7 +371,7 @@ public static void TryAddScoped(this IServiceCollection collection) /// The type of the service to add. /// The type of the implementation to use. /// The . - public static void TryAddScoped(this IServiceCollection collection) + public static void TryAddScoped(this IServiceCollection collection) where TService : class where TImplementation : class, TService { @@ -406,7 +407,7 @@ public static void TryAddScoped( /// The type of the service to register. public static void TryAddSingleton( this IServiceCollection collection, - Type service) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type service) { if (collection == null) { @@ -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) { @@ -492,7 +493,7 @@ public static void TryAddSingleton( /// /// The type of the service to add. /// The . - public static void TryAddSingleton(this IServiceCollection collection) + public static void TryAddSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection collection) where TService : class { if (collection == null) @@ -511,7 +512,7 @@ public static void TryAddSingleton(this IServiceCollection collection) /// The type of the service to add. /// The type of the implementation to use. /// The . - public static void TryAddSingleton(this IServiceCollection collection) + public static void TryAddSingleton(this IServiceCollection collection) where TService : class where TImplementation : class, TService { 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 a8e1db4822e590..d1955eaf4e8998 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 @@ -16,6 +16,9 @@ Link="Common\src\Extensions\ActivatorUtilities\ActivatorUtilitiesConstructorAttribute.cs" /> + + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.cs index 23cf01a1272d39..1de2b83d156f0c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceCollectionServiceExtensions.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.DependencyInjection { @@ -23,7 +24,7 @@ public static class ServiceCollectionServiceExtensions public static IServiceCollection AddTransient( this IServiceCollection services, Type serviceType, - Type implementationType) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { if (services == null) { @@ -86,7 +87,7 @@ public static IServiceCollection AddTransient( /// The to add the service to. /// A reference to this instance after the operation has completed. /// - public static IServiceCollection AddTransient(this IServiceCollection services) + public static IServiceCollection AddTransient(this IServiceCollection services) where TService : class where TImplementation : class, TService { @@ -108,7 +109,7 @@ public static IServiceCollection AddTransient(this IS /// public static IServiceCollection AddTransient( this IServiceCollection services, - Type serviceType) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType) { if (services == null) { @@ -131,7 +132,7 @@ public static IServiceCollection AddTransient( /// The to add the service to. /// A reference to this instance after the operation has completed. /// - public static IServiceCollection AddTransient(this IServiceCollection services) + public static IServiceCollection AddTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection services) where TService : class { if (services == null) @@ -201,8 +202,6 @@ public static IServiceCollection AddTransient( return services.AddTransient(typeof(TService), implementationFactory); } - - /// /// Adds a scoped service of the type specified in with an /// implementation of the type specified in to the @@ -216,7 +215,7 @@ public static IServiceCollection AddTransient( public static IServiceCollection AddScoped( this IServiceCollection services, Type serviceType, - Type implementationType) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { if (services == null) { @@ -279,7 +278,7 @@ public static IServiceCollection AddScoped( /// The to add the service to. /// A reference to this instance after the operation has completed. /// - public static IServiceCollection AddScoped(this IServiceCollection services) + public static IServiceCollection AddScoped(this IServiceCollection services) where TService : class where TImplementation : class, TService { @@ -301,7 +300,7 @@ public static IServiceCollection AddScoped(this IServ /// public static IServiceCollection AddScoped( this IServiceCollection services, - Type serviceType) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType) { if (services == null) { @@ -324,7 +323,7 @@ public static IServiceCollection AddScoped( /// The to add the service to. /// A reference to this instance after the operation has completed. /// - public static IServiceCollection AddScoped(this IServiceCollection services) + public static IServiceCollection AddScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection services) where TService : class { if (services == null) @@ -408,7 +407,7 @@ public static IServiceCollection AddScoped( public static IServiceCollection AddSingleton( this IServiceCollection services, Type serviceType, - Type implementationType) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { if (services == null) { @@ -471,7 +470,7 @@ public static IServiceCollection AddSingleton( /// The to add the service to. /// A reference to this instance after the operation has completed. /// - public static IServiceCollection AddSingleton(this IServiceCollection services) + public static IServiceCollection AddSingleton(this IServiceCollection services) where TService : class where TImplementation : class, TService { @@ -493,7 +492,7 @@ public static IServiceCollection AddSingleton(this IS /// public static IServiceCollection AddSingleton( this IServiceCollection services, - Type serviceType) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type serviceType) { if (services == null) { @@ -516,7 +515,7 @@ public static IServiceCollection AddSingleton( /// The to add the service to. /// A reference to this instance after the operation has completed. /// - public static IServiceCollection AddSingleton(this IServiceCollection services) + public static IServiceCollection AddSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TService>(this IServiceCollection services) where TService : class { if (services == null) @@ -651,7 +650,7 @@ public static IServiceCollection AddSingleton( private static IServiceCollection Add( IServiceCollection collection, Type serviceType, - Type implementationType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime) { var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs index d5fed233c6b59c..57a6d8d33f7d7d 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.DependencyInjection { @@ -20,7 +21,7 @@ public class ServiceDescriptor /// The of the service. public ServiceDescriptor( Type serviceType, - Type implementationType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, ServiceLifetime lifetime) : this(serviceType, lifetime) { @@ -96,6 +97,7 @@ private ServiceDescriptor(Type serviceType, ServiceLifetime lifetime) public Type ServiceType { get; } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] public Type? ImplementationType { get; } public object? ImplementationInstance { get; } @@ -151,7 +153,7 @@ internal Type GetImplementationType() /// The type of the service. /// The type of the implementation. /// A new instance of . - public static ServiceDescriptor Transient() + public static ServiceDescriptor Transient() where TService : class where TImplementation : class, TService { @@ -166,7 +168,9 @@ public static ServiceDescriptor Transient() /// The type of the service. /// The type of the implementation. /// A new instance of . - public static ServiceDescriptor Transient(Type service, Type implementationType) + public static ServiceDescriptor Transient( + Type service, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { if (service == null) { @@ -254,7 +258,7 @@ public static ServiceDescriptor Transient(Type service, FuncThe type of the service. /// The type of the implementation. /// A new instance of . - public static ServiceDescriptor Scoped() + public static ServiceDescriptor Scoped() where TService : class where TImplementation : class, TService { @@ -269,7 +273,9 @@ public static ServiceDescriptor Scoped() /// The type of the service. /// The type of the implementation. /// A new instance of . - public static ServiceDescriptor Scoped(Type service, Type implementationType) + public static ServiceDescriptor Scoped( + Type service, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { return Describe(service, implementationType, ServiceLifetime.Scoped); } @@ -347,7 +353,7 @@ public static ServiceDescriptor Scoped(Type service, FuncThe type of the service. /// The type of the implementation. /// A new instance of . - public static ServiceDescriptor Singleton() + public static ServiceDescriptor Singleton() where TService : class where TImplementation : class, TService { @@ -362,7 +368,9 @@ public static ServiceDescriptor Singleton() /// The type of the service. /// The type of the implementation. /// A new instance of . - public static ServiceDescriptor Singleton(Type service, Type implementationType) + public static ServiceDescriptor Singleton( + Type service, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType) { if (service == null) { @@ -488,7 +496,7 @@ public static ServiceDescriptor Singleton( return new ServiceDescriptor(serviceType, implementationInstance); } - private static ServiceDescriptor Describe(ServiceLifetime lifetime) + private static ServiceDescriptor Describe(ServiceLifetime lifetime) where TService : class where TImplementation : class, TService { @@ -507,7 +515,10 @@ private static ServiceDescriptor Describe(ServiceLife /// The type of the implementation. /// The lifetime of the service. /// A new instance of . - public static ServiceDescriptor Describe(Type serviceType, Type implementationType, ServiceLifetime lifetime) + public static ServiceDescriptor Describe( + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, + ServiceLifetime lifetime) { return new ServiceDescriptor(serviceType, implementationType, lifetime); } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj index 17dc779a71056e..de407f2933ae4f 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj @@ -25,6 +25,12 @@ Link="Common\src\Extensions\TypeNameHelper\TypeNameHelper.cs" /> + + + + + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index 2bf5ee16fc8e15..4aec44848ae0e1 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -5,6 +5,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using Microsoft.Extensions.Internal; @@ -244,16 +245,16 @@ private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type return null; } - private ServiceCallSite CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, + private ServiceCallSite CreateConstructorCallSite( + ResultCache lifetime, + Type serviceType, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type implementationType, CallSiteChain callSiteChain) { try { callSiteChain.Add(serviceType, implementationType); - ConstructorInfo[] constructors = implementationType.GetTypeInfo() - .DeclaredConstructors - .Where(constructor => constructor.IsPublic) - .ToArray(); + ConstructorInfo[] constructors = implementationType.GetConstructors(); ServiceCallSite[] parameterCallSites = null; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/ActivatorUtilitiesTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/ActivatorUtilitiesTests.cs new file mode 100644 index 00000000000000..eef18d380d1e25 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/ActivatorUtilitiesTests.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using Microsoft.Extensions.DependencyInjection; + +class Program +{ + static int Main(string[] args) + { + ServiceProvider provider = new ServiceCollection().BuildServiceProvider(); + + // ActivatorUtilities.CreateFactory fails due to https://github.com/mono/linker/issues/1398 + //ObjectFactory factory = ActivatorUtilities.CreateFactory(typeof(ServiceA), Array.Empty()); + //ServiceA serviceA = factory(provider, null) as ServiceA; + ServiceB serviceB = ActivatorUtilities.CreateInstance(provider, typeof(ServiceB)) as ServiceB; + ServiceC serviceC = ActivatorUtilities.CreateInstance(provider); + ServiceD serviceD = ActivatorUtilities.GetServiceOrCreateInstance(provider, typeof(ServiceD)) as ServiceD; + ServiceE serviceE = ActivatorUtilities.GetServiceOrCreateInstance(provider); + + if (//serviceA is null || + serviceB is null || + serviceC is null || + serviceD is null || + serviceE is null) + { + return -1; + } + + return 100; + } + + private class ServiceA { } + private class ServiceB { } + private class ServiceC { } + private class ServiceD { } + private class ServiceE { } +} diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/Microsoft.Extensions.DependencyInjection.TrimmingTests.proj b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/Microsoft.Extensions.DependencyInjection.TrimmingTests.proj new file mode 100644 index 00000000000000..e1f5ef6af8cd5b --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/Microsoft.Extensions.DependencyInjection.TrimmingTests.proj @@ -0,0 +1,14 @@ + + + + + Microsoft.Extensions.DependencyInjection + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/ServiceCollectionExtensionsTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/ServiceCollectionExtensionsTests.cs new file mode 100644 index 00000000000000..58a1c8b10ab40c --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/TrimmingTests/ServiceCollectionExtensionsTests.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.DependencyInjection; + +class Program +{ + static int Main(string[] args) + { + IServiceCollection descriptors = new ServiceCollection(); + descriptors.AddTransient(); + descriptors.AddScoped(typeof(ServiceB)); + descriptors.AddSingleton(typeof(IServiceC), typeof(ServiceC)); + + descriptors.AddTransient(); + descriptors.AddTransient(); + descriptors.AddTransient(typeof(IServiceF), typeof(ServiceF)); + + descriptors.AddTransient(); + descriptors.AddTransient(typeof(Logger<>)); + + descriptors.AddTransient(); + descriptors.AddTransient(); + + ServiceProvider provider = descriptors.BuildServiceProvider(); + + if (provider.GetService() is null || + provider.GetService() is null || + provider.GetService() is null || + provider.GetService()?.ServiceE?.ServiceD is null || + provider.GetService>() is null) + { + return -1; + } + + int hServices = 0; + foreach (IServiceH h in provider.GetServices()) + { + hServices++; + if (h == null) + { + return -1; + } + } + + if (hServices != 2) + { + return -1; + } + + return 100; + } + + private class ServiceA { } + private class ServiceB { } + private interface IServiceC { } + private class ServiceC : IServiceC { } + + public interface IServiceD { } + public interface IServiceE { IServiceD ServiceD { get; } } + public interface IServiceF { IServiceE ServiceE { get; } } + public class ServiceD : IServiceD + { + } + public class ServiceE : IServiceE + { + public IServiceD ServiceD { get; } + public ServiceE(IServiceD d) { ServiceD = d; } + } + public class ServiceF : IServiceF + { + public IServiceE ServiceE { get; } + public ServiceF(IServiceE e) { ServiceE = e; } + } + + public class Logger { } + public interface IServiceG { } + public class ServiceG : IServiceG { } + + public interface IServiceH { } + public class ServiceH1 : IServiceH { } + public class ServiceH2 : IServiceH { } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs index eefc9c442925bb..2d82ed0c0e7f50 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs @@ -13,7 +13,12 @@ namespace System.Diagnostics.CodeAnalysis /// . So it is always preserved in the compiled assembly. /// [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] - public sealed class UnconditionalSuppressMessageAttribute : Attribute +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class UnconditionalSuppressMessageAttribute : Attribute { /// /// Initializes a new instance of the