This repository was archived by the owner on Nov 2, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 311
This repository was archived by the owner on Nov 2, 2018. It is now read-only.
Support constrained open generic types #471
Copy link
Copy link
Closed
Description
If I register a collection of open generics, some of the open generics may be constrained. Consider the interface and implementations:
public interface IFakeOpenGenericService<TValue>
{
TValue Value { get; }
}
public class FakeOpenGenericService<TVal> : IFakeOpenGenericService<TVal>
{
public FakeOpenGenericService(TVal value)
{
Value = value;
}
public TVal Value { get; }
}
public class ConstrainedFakeOpenGenericService<TVal> : IFakeOpenGenericService<TVal>
where TVal : PocoClass
{
public ConstrainedFakeOpenGenericService(TVal value)
{
Value = value;
}
public TVal Value { get; }
}
If I register multiple services:
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>));
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ConstrainedFakeOpenGenericService<>));
And try to resolve, the version that adheres to all constraints works, but if I try to get a collection with a generic parameter that doesn't match the constraint, I get an exception:
var allServices = provider.GetServices<IFakeOpenGenericService<PocoClass>>().ToList();
var constrainedServices = provider.GetServices<IFakeOpenGenericService<IFakeSingletonService>>().ToList();
Exception:
System.ArgumentException : GenericArguments[0], 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeSingletonService', on 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.ConstrainedFakeOpenGenericService`1[TVal]' violates the constraint of type 'TVal'.
---- System.TypeLoadException : GenericArguments[0], 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeSingletonService', on 'Microsoft.Extensions.DependencyInjection.Specification.Fakes.ConstrainedFakeOpenGenericService`1[TVal]' violates the constraint of type parameter 'TVal'.
Stack Trace:
at System.RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
at System.RuntimeType.MakeGenericType(Type[] instantiation)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection\ServiceLookup\GenericService.cs(26,0): at Microsoft.Extensions.DependencyInjection.ServiceLookup.GenericService.GetService(Type closedServiceType)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection\ServiceLookup\ServiceTable.cs(102,0): at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceTable.TryGetEntry(Type serviceType, ServiceEntry& entry)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection\ServiceLookup\OpenIEnumerableService.cs(28,0): at Microsoft.Extensions.DependencyInjection.ServiceLookup.OpenIEnumerableService.GetService(Type closedServiceType)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection\ServiceLookup\ServiceTable.cs(102,0): at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceTable.TryGetEntry(Type serviceType, ServiceEntry& entry)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection\ServiceProvider.cs(114,0): at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetServiceCallSite(Type serviceType, ISet`1 callSiteChain)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection\ServiceProvider.cs(73,0): at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType, ServiceProvider serviceProvider)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection\Internal\ConcurrentDictionaryExtensions.cs(24,0): at System.Collections.Concurrent.ConcurrentDictionaryExtensions.GetOrAdd[TKey,TValue,TArg](ConcurrentDictionary`2 dictionary, TKey key, Func`3 valueFactory, TArg arg)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection\ServiceProvider.cs(64,0): at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection.Abstractions\ServiceProviderServiceExtensions.cs(56,0): at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection.Abstractions\ServiceProviderServiceExtensions.cs(79,0): at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection.Abstractions\ServiceProviderServiceExtensions.cs(95,0): at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetServices[T](IServiceProvider provider)
C:\dev\aspnet-DependencyInjection\src\Microsoft.Extensions.DependencyInjection.Specification.Tests\DependencyInjectionSpecificationTests.cs(561,0): at Microsoft.Extensions.DependencyInjection.Specification.DependencyInjectionSpecificationTests.ConstrainedOpenGenericServicesCanBeResolved()
----- Inner Stack Trace -----
at System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, Int32 numGenericArgs, ObjectHandleOnStack type)
at System.RuntimeTypeHandle.Instantiate(Type[] inst)
at System.RuntimeType.MakeGenericType(Type[] instantiation)
Expected: constrained open generics are tested before attempted to instantiate. It looks like the only way to reliably test is to try-catch-swallow, see http://stackoverflow.com/a/4864565/58508
PR with failing test coming shortly.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels