Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,4 @@
<data name="AsyncDisposableServiceDispose" xml:space="preserve">
<value>'{0}' type only implements IAsyncDisposable. Use DisposeAsync to dispose the container.</value>
</data>
<data name="GenericConstraintViolation" xml:space="preserve">
<value>Generic constraints violated for type '{0}' while attempting to activate '{1}'.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ private ServiceCallSite TryCreateOpenGeneric(Type serviceType, CallSiteChain cal
if (serviceType.IsConstructedGenericType
&& _descriptorLookup.TryGetValue(serviceType.GetGenericTypeDefinition(), out ServiceDescriptorCacheItem descriptor))
{
return TryCreateOpenGeneric(descriptor.Last, serviceType, callSiteChain, DefaultSlot, true);
return TryCreateOpenGeneric(descriptor.Last, serviceType, callSiteChain, DefaultSlot);
}

return null;
Expand Down Expand Up @@ -164,7 +164,7 @@ private ServiceCallSite TryCreateEnumerable(Type serviceType, CallSiteChain call
{
ServiceDescriptor descriptor = _descriptors[i];
ServiceCallSite callSite = TryCreateExact(descriptor, itemType, callSiteChain, slot) ??
TryCreateOpenGeneric(descriptor, itemType, callSiteChain, slot, false);
TryCreateOpenGeneric(descriptor, itemType, callSiteChain, slot);

if (callSite != null)
{
Expand Down Expand Up @@ -230,28 +230,14 @@ private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type servic
return null;
}

private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation)
private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot)
{
if (serviceType.IsConstructedGenericType &&
serviceType.GetGenericTypeDefinition() == descriptor.ServiceType)
{
Debug.Assert(descriptor.ImplementationType != null, "descriptor.ImplementationType != null");
var lifetime = new ResultCache(descriptor.Lifetime, serviceType, slot);
Type closedType;
try
{
closedType = descriptor.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments);
}
catch (ArgumentException ex)
{
if (throwOnConstraintViolation)
{
throw new InvalidOperationException(SR.Format(SR.GenericConstraintViolation, serviceType, descriptor.ImplementationType), ex);
}

return null;
}

Type closedType = descriptor.ImplementationType.MakeGenericType(serviceType.GenericTypeArguments);
return CreateConstructorCallSite(lifetime, serviceType, closedType, callSiteChain);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,9 @@

namespace Microsoft.Extensions.DependencyInjection.Specification
{
public class AutofacDependencyInjectionSpecificationTests : SkippableDependencyInjectionSpecificationTests
public class AutofacDependencyInjectionSpecificationTests: DependencyInjectionSpecificationTests
{
public override string[] SkippedTests => new[]
{
"PublicNoArgCtorConstrainedOpenGenericServicesCanBeResolved"
};

protected override IServiceProvider CreateServiceProviderImpl(IServiceCollection serviceCollection)
protected override IServiceProvider CreateServiceProvider(IServiceCollection serviceCollection)
{
var builder = new ContainerBuilder();
builder.Populate(serviceCollection);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,9 @@

namespace Microsoft.Extensions.DependencyInjection.Specification
{
public class StashBoxDependencyInjectionSpecificationTests : SkippableDependencyInjectionSpecificationTests
public class StashBoxDependencyInjectionSpecificationTests: DependencyInjectionSpecificationTests
{
public override string[] SkippedTests => new[]
{
"PublicNoArgCtorConstrainedOpenGenericServicesCanBeResolved",
"SelfReferencingConstrainedOpenGenericServicesCanBeResolved",
"ClassConstrainedOpenGenericServicesCanBeResolved"
};

protected override IServiceProvider CreateServiceProviderImpl(IServiceCollection serviceCollection)
protected override IServiceProvider CreateServiceProvider(IServiceCollection serviceCollection)
{
return serviceCollection.UseStashbox();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,160 +591,6 @@ public void OpenGenericServicesCanBeResolved()
Assert.Same(singletonService, genericService.Value);
}

[Fact]
public void ConstrainedOpenGenericServicesCanBeResolved()
{
// Arrange
var collection = new TestServiceCollection();
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>));
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ConstrainedFakeOpenGenericService<>));
var poco = new PocoClass();
collection.AddSingleton(poco);
collection.AddSingleton<IFakeSingletonService, FakeService>();
var provider = CreateServiceProvider(collection);
// Act
var allServices = provider.GetServices<IFakeOpenGenericService<PocoClass>>().ToList();
var constrainedServices = provider.GetServices<IFakeOpenGenericService<IFakeSingletonService>>().ToList();
var singletonService = provider.GetService<IFakeSingletonService>();
// Assert
Assert.Equal(2, allServices.Count);
Assert.Same(poco, allServices[0].Value);
Assert.Same(poco, allServices[1].Value);
Assert.Equal(1, constrainedServices.Count);
Assert.Same(singletonService, constrainedServices[0].Value);
}

[Fact]
public void ConstrainedOpenGenericServicesReturnsEmptyWithNoMatches()
{
// Arrange
var collection = new TestServiceCollection();
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ConstrainedFakeOpenGenericService<>));
collection.AddSingleton<IFakeSingletonService, FakeService>();
var provider = CreateServiceProvider(collection);
// Act
var constrainedServices = provider.GetServices<IFakeOpenGenericService<IFakeSingletonService>>().ToList();
// Assert
Assert.Equal(0, constrainedServices.Count);
}

[Fact]
public void InterfaceConstrainedOpenGenericServicesCanBeResolved()
{
// Arrange
var collection = new TestServiceCollection();
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>));
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithInterfaceConstraint<>));
var enumerableVal = new ClassImplementingIEnumerable();
collection.AddSingleton(enumerableVal);
collection.AddSingleton<IFakeSingletonService, FakeService>();
var provider = CreateServiceProvider(collection);
// Act
var allServices = provider.GetServices<IFakeOpenGenericService<ClassImplementingIEnumerable>>().ToList();
var constrainedServices = provider.GetServices<IFakeOpenGenericService<IFakeSingletonService>>().ToList();
var singletonService = provider.GetService<IFakeSingletonService>();
// Assert
Assert.Equal(2, allServices.Count);
Assert.Same(enumerableVal, allServices[0].Value);
Assert.Same(enumerableVal, allServices[1].Value);
Assert.Equal(1, constrainedServices.Count);
Assert.Same(singletonService, constrainedServices[0].Value);
}

[Fact]
public void PublicNoArgCtorConstrainedOpenGenericServicesCanBeResolved()
{
// Arrange
var collection = new TestServiceCollection();
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithNoConstraints<>));
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithNewConstraint<>));
var provider = CreateServiceProvider(collection);
// Act
var allServices = provider.GetServices<IFakeOpenGenericService<PocoClass>>().ToList();
var constrainedServices = provider.GetServices<IFakeOpenGenericService<ClassWithPrivateCtor>>().ToList();
// Assert
Assert.Equal(2, allServices.Count);
Assert.Equal(1, constrainedServices.Count);
}

[Fact]
public void ClassConstrainedOpenGenericServicesCanBeResolved()
{
// Arrange
var collection = new TestServiceCollection();
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithNoConstraints<>));
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithClassConstraint<>));
var provider = CreateServiceProvider(collection);
// Act
var allServices = provider.GetServices<IFakeOpenGenericService<PocoClass>>().ToList();
var constrainedServices = provider.GetServices<IFakeOpenGenericService<int>>().ToList();
// Assert
Assert.Equal(2, allServices.Count);
Assert.Equal(1, constrainedServices.Count);
}

[Fact]
public void StructConstrainedOpenGenericServicesCanBeResolved()
{
// Arrange
var collection = new TestServiceCollection();
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithNoConstraints<>));
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithStructConstraint<>));
var provider = CreateServiceProvider(collection);
// Act
var allServices = provider.GetServices<IFakeOpenGenericService<int>>().ToList();
var constrainedServices = provider.GetServices<IFakeOpenGenericService<PocoClass>>().ToList();
// Assert
Assert.Equal(2, allServices.Count);
Assert.Equal(1, constrainedServices.Count);
}

[Fact]
public void AbstractClassConstrainedOpenGenericServicesCanBeResolved()
{
// Arrange
var collection = new TestServiceCollection();
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>));
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithAbstractClassConstraint<>));
var poco = new PocoClass();
collection.AddSingleton(poco);
var classInheritingClassInheritingAbstractClass = new ClassInheritingClassInheritingAbstractClass();
collection.AddSingleton(classInheritingClassInheritingAbstractClass);
var provider = CreateServiceProvider(collection);
// Act
var allServices = provider.GetServices<IFakeOpenGenericService<ClassInheritingClassInheritingAbstractClass>>().ToList();
var constrainedServices = provider.GetServices<IFakeOpenGenericService<PocoClass>>().ToList();
// Assert
Assert.Equal(2, allServices.Count);
Assert.Same(classInheritingClassInheritingAbstractClass, allServices[0].Value);
Assert.Same(classInheritingClassInheritingAbstractClass, allServices[1].Value);
Assert.Equal(1, constrainedServices.Count);
Assert.Same(poco, constrainedServices[0].Value);
}

[Fact]
public void SelfReferencingConstrainedOpenGenericServicesCanBeResolved()
{
// Arrange
var collection = new TestServiceCollection();
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>));
collection.AddTransient(typeof(IFakeOpenGenericService<>), typeof(ClassWithSelfReferencingConstraint<>));
var poco = new PocoClass();
collection.AddSingleton(poco);
var selfComparable = new ClassImplementingIComparable();
collection.AddSingleton(selfComparable);
var provider = CreateServiceProvider(collection);
// Act
var allServices = provider.GetServices<IFakeOpenGenericService<ClassImplementingIComparable>>().ToList();
var constrainedServices = provider.GetServices<IFakeOpenGenericService<PocoClass>>().ToList();
// Assert
Assert.Equal(2, allServices.Count);
Assert.Same(selfComparable, allServices[0].Value);
Assert.Same(selfComparable, allServices[1].Value);
Assert.Equal(1, constrainedServices.Count);
Assert.Same(poco, constrainedServices[0].Value);
}

[Fact]
public void ClosedServicesPreferredOverOpenGenericServices()
{
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading