Skip to content

Commit 4cfc831

Browse files
authored
Fix NRE when default value is null and ServiceCallSite is not found (#44877)
1 parent 5660c4a commit 4cfc831

File tree

6 files changed

+54
-3
lines changed

6 files changed

+54
-3
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<Project>
2+
<Import Project="..\Directory.Build.props" />
3+
<PropertyGroup>
4+
<PackageVersion>5.0.1</PackageVersion>
5+
<AssemblyVersion>5.0.0.1</AssemblyVersion>
6+
</PropertyGroup>
7+
</Project>

src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ConstantCallSite.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ namespace Microsoft.Extensions.DependencyInjection.ServiceLookup
77
{
88
internal class ConstantCallSite : ServiceCallSite
99
{
10+
private readonly Type _serviceType;
1011
internal object DefaultValue { get; }
1112

1213
public ConstantCallSite(Type serviceType, object defaultValue): base(ResultCache.None)
1314
{
15+
_serviceType = serviceType ?? throw new ArgumentNullException(nameof(serviceType));
1416
if (defaultValue != null && !serviceType.IsInstanceOfType(defaultValue))
1517
{
1618
throw new ArgumentException(SR.Format(SR.ConstantCantBeConvertedToServiceType, defaultValue.GetType(), serviceType));
@@ -19,8 +21,8 @@ public ConstantCallSite(Type serviceType, object defaultValue): base(ResultCache
1921
DefaultValue = defaultValue;
2022
}
2123

22-
public override Type ServiceType => DefaultValue.GetType();
23-
public override Type ImplementationType => DefaultValue.GetType();
24+
public override Type ServiceType => DefaultValue?.GetType() ?? _serviceType;
25+
public override Type ImplementationType => DefaultValue?.GetType() ?? _serviceType;
2426
public override CallSiteKind Kind { get; } = CallSiteKind.Constant;
2527
}
2628
}

src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/CallSiteTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,37 @@ public void DoesNotThrowWhenServiceIsUsedAsEnumerableAndNotInOneCallSite()
264264
Assert.NotNull(compileCallSite);
265265
}
266266

267+
[Theory]
268+
[InlineData(ServiceProviderMode.Default)]
269+
[InlineData(ServiceProviderMode.Dynamic)]
270+
[InlineData(ServiceProviderMode.Runtime)]
271+
[InlineData(ServiceProviderMode.Expressions)]
272+
[InlineData(ServiceProviderMode.ILEmit)]
273+
private void NoServiceCallsite_DefaultValueNull_DoesNotThrow(ServiceProviderMode mode)
274+
{
275+
var descriptors = new ServiceCollection();
276+
descriptors.AddTransient<ServiceG>();
277+
278+
var provider = descriptors.BuildServiceProvider(mode);
279+
ServiceF instance = ActivatorUtilities.CreateInstance<ServiceF>(provider);
280+
281+
Assert.NotNull(instance);
282+
}
283+
284+
private interface IServiceG
285+
{
286+
}
287+
288+
private class ServiceG
289+
{
290+
public ServiceG(IServiceG service = null) { }
291+
}
292+
293+
private class ServiceF
294+
{
295+
public ServiceF(ServiceG service) { }
296+
}
297+
267298
private class ServiceD
268299
{
269300
public ServiceD(IEnumerable<ServiceA> services)

src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderCompilationTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace Microsoft.Extensions.DependencyInjection.Tests
1212
public class ServiceProviderCompilationTest
1313
{
1414
[Theory]
15+
[InlineData(ServiceProviderMode.Default, typeof(I999))]
1516
[InlineData(ServiceProviderMode.Dynamic, typeof(I999))]
1617
[InlineData(ServiceProviderMode.Runtime, typeof(I999))]
1718
[InlineData(ServiceProviderMode.ILEmit, typeof(I999))]

src/libraries/libraries-packages.proj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<ProjectReference Include="$(MSBuildThisFileDirectory)*\pkg\**\*.pkgproj" Condition="('$(BuildAllConfigurations)' == 'true' or '$(DotNetBuildFromSource)' == 'true') And '$(BuildAllOOBPackages)' == 'true'" />
2020
<!-- If setting BuildAllOOBPackages to false, add bellow the individual OOB packages you want to continue to build -->
2121
<ProjectReference Include="$(LibrariesProjectRoot)\System.IO.Pipelines\pkg\System.IO.Pipelines.pkgproj" Condition="'$(BuildAllConfigurations)' == 'true'" />
22+
<ProjectReference Include="$(LibrariesProjectRoot)\Microsoft.Extensions.DependencyInjection\pkg\Microsoft.Extensions.DependencyInjection.pkgproj" Condition="'$(BuildAllConfigurations)' == 'true'" />
2223
<ProjectReference Include="$(LibrariesProjectRoot)\System.Security.Cryptography.Pkcs\pkg\System.Security.Cryptography.Pkcs.pkgproj" Condition="'$(BuildAllConfigurations)' == 'true'" />
2324
</ItemGroup>
2425

src/libraries/pkg/baseline/packageIndex.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,11 +507,20 @@
507507
"3.1.0",
508508
"3.1.1",
509509
"3.1.2",
510+
"3.1.3",
511+
"3.1.4",
512+
"3.1.5",
513+
"3.1.6",
514+
"3.1.7",
515+
"3.1.8",
516+
"3.1.9",
517+
"3.1.10",
510518
"5.0.0"
511519
],
512520
"InboxOn": {},
513521
"AssemblyVersionInPackageVersion": {
514-
"5.0.0.0": "5.0.0"
522+
"5.0.0.0": "5.0.0",
523+
"5.0.0.1": "5.0.1"
515524
}
516525
},
517526
"Microsoft.Extensions.DependencyInjection.Abstractions": {

0 commit comments

Comments
 (0)