Skip to content

Commit e3d9bfd

Browse files
authored
Return null instead of throwing in ServiceDescriptor.ImplementationInstance\Type\Factory if a keyed service (#105776)
1 parent 8e1904c commit e3d9bfd

File tree

3 files changed

+37
-48
lines changed

3 files changed

+37
-48
lines changed

src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Resources/Strings.resx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,7 @@
170170
<data name="KeyedServicesNotSupported" xml:space="preserve">
171171
<value>This service provider doesn't support keyed services.</value>
172172
</data>
173-
<data name="KeyedDescriptorMisuse" xml:space="preserve">
174-
<value>This service descriptor is keyed. Your service provider may not support keyed services.</value>
175-
</data>
176173
<data name="NonKeyedDescriptorMisuse" xml:space="preserve">
177174
<value>This service descriptor is not keyed.</value>
178175
</data>
179-
</root>
176+
</root>

src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceDescriptor.cs

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -152,24 +152,22 @@ private ServiceDescriptor(Type serviceType, object? serviceKey, ServiceLifetime
152152
private Type? _implementationType;
153153

154154
/// <summary>
155-
/// Gets the <see cref="Type"/> that implements the service.
155+
/// Gets the <see cref="Type"/> that implements the service,
156+
/// or returns <see langword="null"/> if <see cref="IsKeyedService"/> is <see langword="true"/>.
156157
/// </summary>
158+
/// <remarks>
159+
/// If <see cref="IsKeyedService"/> is <see langword="true"/>, <see cref="KeyedImplementationType"/> should be called instead.
160+
/// </remarks>
157161
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
158-
public Type? ImplementationType
159-
{
160-
get
161-
{
162-
if (IsKeyedService)
163-
{
164-
ThrowKeyedDescriptor();
165-
}
166-
return _implementationType;
167-
}
168-
}
162+
public Type? ImplementationType => IsKeyedService ? null : _implementationType;
169163

170164
/// <summary>
171-
/// Gets the <see cref="Type"/> that implements the service.
165+
/// Gets the <see cref="Type"/> that implements the service,
166+
/// or throws <see cref="InvalidOperationException"/> if <see cref="IsKeyedService"/> is <see langword="false"/>.
172167
/// </summary>
168+
/// <remarks>
169+
/// If <see cref="IsKeyedService"/> is <see langword="false"/>, <see cref="ImplementationType"/> should be called instead.
170+
/// </remarks>
173171
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
174172
public Type? KeyedImplementationType
175173
{
@@ -186,23 +184,21 @@ public Type? KeyedImplementationType
186184
private object? _implementationInstance;
187185

188186
/// <summary>
189-
/// Gets the instance that implements the service.
187+
/// Gets the instance that implements the service,
188+
/// or returns <see langword="null"/> if <see cref="IsKeyedService"/> is <see langword="true"/>.
190189
/// </summary>
191-
public object? ImplementationInstance
192-
{
193-
get
194-
{
195-
if (IsKeyedService)
196-
{
197-
ThrowKeyedDescriptor();
198-
}
199-
return _implementationInstance;
200-
}
201-
}
190+
/// <remarks>
191+
/// If <see cref="IsKeyedService"/> is <see langword="true"/>, <see cref="KeyedImplementationInstance"/> should be called instead.
192+
/// </remarks>
193+
public object? ImplementationInstance => IsKeyedService ? null : _implementationInstance;
202194

203195
/// <summary>
204-
/// Gets the instance that implements the service.
196+
/// Gets the instance that implements the service,
197+
/// or throws <see cref="InvalidOperationException"/> if <see cref="IsKeyedService"/> is <see langword="false"/>.
205198
/// </summary>
199+
/// <remarks>
200+
/// If <see cref="IsKeyedService"/> is <see langword="false"/>, <see cref="ImplementationInstance"/> should be called instead.
201+
/// </remarks>
206202
public object? KeyedImplementationInstance
207203
{
208204
get
@@ -218,23 +214,21 @@ public object? KeyedImplementationInstance
218214
private object? _implementationFactory;
219215

220216
/// <summary>
221-
/// Gets the factory used for creating service instances.
217+
/// Gets the factory used for creating service instance,
218+
/// or returns <see langword="null"/> if <see cref="IsKeyedService"/> is <see langword="true"/>.
222219
/// </summary>
223-
public Func<IServiceProvider, object>? ImplementationFactory
224-
{
225-
get
226-
{
227-
if (IsKeyedService)
228-
{
229-
ThrowKeyedDescriptor();
230-
}
231-
return (Func<IServiceProvider, object>?)_implementationFactory;
232-
}
233-
}
220+
/// <remarks>
221+
/// If <see cref="IsKeyedService"/> is <see langword="true"/>, <see cref="KeyedImplementationFactory"/> should be called instead.
222+
/// </remarks>
223+
public Func<IServiceProvider, object>? ImplementationFactory => IsKeyedService ? null : (Func<IServiceProvider, object>?) _implementationFactory;
234224

235225
/// <summary>
236-
/// Gets the factory used for creating Keyed service instances.
226+
/// Gets the factory used for creating Keyed service instances,
227+
/// or throws <see cref="InvalidOperationException"/> if <see cref="IsKeyedService"/> is <see langword="false"/>.
237228
/// </summary>
229+
/// <remarks>
230+
/// If <see cref="IsKeyedService"/> is <see langword="false"/>, <see cref="ImplementationFactory"/> should be called instead.
231+
/// </remarks>
238232
public Func<IServiceProvider, object?, object>? KeyedImplementationFactory
239233
{
240234
get
@@ -1058,8 +1052,6 @@ private string DebuggerToString()
10581052
return debugText;
10591053
}
10601054

1061-
private static void ThrowKeyedDescriptor() => throw new InvalidOperationException(SR.KeyedDescriptorMisuse);
1062-
10631055
private static void ThrowNonKeyedDescriptor() => throw new InvalidOperationException(SR.NonKeyedDescriptorMisuse);
10641056
}
10651057
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,9 @@ public static TheoryData NotNullServiceKeyData
546546
public void NotNullServiceKey_IsKeyedServiceTrue(ServiceDescriptor serviceDescriptor)
547547
{
548548
Assert.True(serviceDescriptor.IsKeyedService);
549-
Assert.Throws<InvalidOperationException>(() => serviceDescriptor.ImplementationInstance);
550-
Assert.Throws<InvalidOperationException>(() => serviceDescriptor.ImplementationType);
551-
Assert.Throws<InvalidOperationException>(() => serviceDescriptor.ImplementationFactory);
549+
Assert.Null(serviceDescriptor.ImplementationInstance);
550+
Assert.Null(serviceDescriptor.ImplementationType);
551+
Assert.Null(serviceDescriptor.ImplementationFactory);
552552
}
553553
}
554554
}

0 commit comments

Comments
 (0)