From f6cf49d5c8c840cb3b1062ee0e9d1b0723db689b Mon Sep 17 00:00:00 2001 From: Jimmy Bogard Date: Mon, 9 Apr 2018 16:30:40 -0500 Subject: [PATCH] Adding test and returning a null if the open generic service fails to close because of a generic constraint. See #471 for discussion. --- .../Fakes/ConstrainedFakeOpenGenericService.cs | 16 ++++++++++++++++ src/DI/ServiceLookup/CallSiteFactory.cs | 11 ++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/DI.Specification.Tests/Fakes/ConstrainedFakeOpenGenericService.cs diff --git a/src/DI.Specification.Tests/Fakes/ConstrainedFakeOpenGenericService.cs b/src/DI.Specification.Tests/Fakes/ConstrainedFakeOpenGenericService.cs new file mode 100644 index 00000000..811d9a33 --- /dev/null +++ b/src/DI.Specification.Tests/Fakes/ConstrainedFakeOpenGenericService.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Extensions.DependencyInjection.Specification.Fakes +{ + public class ConstrainedFakeOpenGenericService : IFakeOpenGenericService + where TVal : PocoClass + { + public ConstrainedFakeOpenGenericService(TVal value) + { + Value = value; + } + + public TVal Value { get; } + } +} \ No newline at end of file diff --git a/src/DI/ServiceLookup/CallSiteFactory.cs b/src/DI/ServiceLookup/CallSiteFactory.cs index 878b64b5..95ccebba 100644 --- a/src/DI/ServiceLookup/CallSiteFactory.cs +++ b/src/DI/ServiceLookup/CallSiteFactory.cs @@ -197,7 +197,16 @@ private IServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type { Debug.Assert(descriptor.ImplementationType != null, "descriptor.ImplementationType != null"); - var closedType = descriptor.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments); + Type closedType; + try + { + closedType = descriptor.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments); + } + catch + { + // This is the only way to reliably test generic constraints. See https://stackoverflow.com/questions/4864496/checking-if-an-object-meets-a-generic-parameter-constraint/4864565#4864565 + return null; + } var constructorCallSite = CreateConstructorCallSite(serviceType, closedType, callSiteChain); return ApplyLifetime(constructorCallSite, Tuple.Create(descriptor, serviceType), descriptor.Lifetime);