diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 845107d..246990e 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@ - 2.2.0 + 3.0.0 dustinsoftware netstandard2.0 $(NoWarn);CS1591 diff --git a/src/StructureMap.Microsoft.DependencyInjection/ContainerExtensions.cs b/src/StructureMap.Microsoft.DependencyInjection/ContainerExtensions.cs index f917a8e..9e361ab 100644 --- a/src/StructureMap.Microsoft.DependencyInjection/ContainerExtensions.cs +++ b/src/StructureMap.Microsoft.DependencyInjection/ContainerExtensions.cs @@ -137,6 +137,11 @@ public static void Register(this IProfileRegistry registry, IEnumerable(); + // Added in MEDI v6 + registry.For() + .LifecycleIs(Lifecycles.Container) + .UseIfNone(); + foreach (var descriptor in descriptors) { registry.Register(descriptor); diff --git a/src/StructureMap.Microsoft.DependencyInjection/StructureMap.Microsoft.DependencyInjection.csproj b/src/StructureMap.Microsoft.DependencyInjection/StructureMap.Microsoft.DependencyInjection.csproj index 009319b..1ad9fc3 100644 --- a/src/StructureMap.Microsoft.DependencyInjection/StructureMap.Microsoft.DependencyInjection.csproj +++ b/src/StructureMap.Microsoft.DependencyInjection/StructureMap.Microsoft.DependencyInjection.csproj @@ -6,6 +6,6 @@ - + diff --git a/src/StructureMap.Microsoft.DependencyInjection/StructureMapServiceProviderIsService.cs b/src/StructureMap.Microsoft.DependencyInjection/StructureMapServiceProviderIsService.cs new file mode 100644 index 0000000..3461c64 --- /dev/null +++ b/src/StructureMap.Microsoft.DependencyInjection/StructureMapServiceProviderIsService.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; + +namespace StructureMap +{ + public sealed class StructureMapServiceProviderIsService : IServiceProviderIsService + { + private readonly IContainer _container; + + public StructureMapServiceProviderIsService(IContainer container) => _container = container; + + // https://github.com/dotnet/dotnet/blob/d25d3482f4c3c509977cc4d959c80cb78b6ad9c8/src/runtime/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs#L778-L803 + public bool IsService(Type serviceType) + { + if (serviceType is null) + { + throw new ArgumentNullException(nameof(serviceType)); + } + + // Querying for an open generic should return false (they aren't resolvable) + if (serviceType.IsGenericTypeDefinition) + { + return false; + } + + if (_container.Model.HasDefaultImplementationFor(serviceType)) + { + return true; + } + + if (serviceType.IsConstructedGenericType && serviceType.GetGenericTypeDefinition() is Type genericDefinition) + { + // We special case IEnumerable since it isn't explicitly registered in the container + // yet we can manifest instances of it when requested. + return genericDefinition == typeof(IEnumerable<>); + } + + return false; + } + } +} diff --git a/test/StructureMap.Microsoft.DependencyInjection.Tests/StructureMap.Microsoft.DependencyInjection.Tests.csproj b/test/StructureMap.Microsoft.DependencyInjection.Tests/StructureMap.Microsoft.DependencyInjection.Tests.csproj index cc9e563..16a9cad 100644 --- a/test/StructureMap.Microsoft.DependencyInjection.Tests/StructureMap.Microsoft.DependencyInjection.Tests.csproj +++ b/test/StructureMap.Microsoft.DependencyInjection.Tests/StructureMap.Microsoft.DependencyInjection.Tests.csproj @@ -14,7 +14,7 @@ - - + + diff --git a/test/StructureMap.Microsoft.DependencyInjection.Tests/StructureMapContainerTests.cs b/test/StructureMap.Microsoft.DependencyInjection.Tests/StructureMapContainerTests.cs index 7793b2b..8a1a9c8 100644 --- a/test/StructureMap.Microsoft.DependencyInjection.Tests/StructureMapContainerTests.cs +++ b/test/StructureMap.Microsoft.DependencyInjection.Tests/StructureMapContainerTests.cs @@ -43,6 +43,7 @@ public void ConfigureAndRegisterDoNotPreventPopulate() { var services = new ServiceCollection(); services.AddTransient(); + services.AddSingleton>(StringComparer.OrdinalIgnoreCase); var container = new Container(); container.Configure(config => @@ -59,6 +60,33 @@ public void ConfigureAndRegisterDoNotPreventPopulate() Assert.NotNull(container.GetInstance()); Assert.NotNull(container.GetInstance()); Assert.NotNull(container.GetInstance()); + + var spis = container.GetInstance(); + Assert.True(spis.IsService(typeof(IFakeService))); + Assert.True(spis.IsService(typeof(IFakeScopedService))); + Assert.True(spis.IsService(typeof(IFakeSingletonService))); + + Assert.False(spis.IsService(typeof(FakeService))); + Assert.False(spis.IsService(typeof(IFakeServiceInstance))); + + // Open generics never resolve + Assert.False(spis.IsService(typeof(IComparer<>))); + Assert.False(spis.IsService(typeof(IEnumerable<>))); + + // Registered closed generic does resolve + Assert.True(spis.IsService(typeof(IComparer))); + + // Unregistered closed generic does not resolve + Assert.False(spis.IsService(typeof(IComparer))); + + // IEnumerable<> of registered types does resolve + Assert.True(spis.IsService(typeof(IEnumerable))); + Assert.True(spis.IsService(typeof(IEnumerable))); + Assert.True(spis.IsService(typeof(IEnumerable))); + + // IEnumerable<> of unregistered types also resolves + Assert.True(spis.IsService(typeof(IEnumerable))); + Assert.True(spis.IsService(typeof(IEnumerable))); } [Fact] @@ -75,6 +103,7 @@ public void ConfigureDoesNotRequirePopulate() Assert.NotNull(container.GetInstance()); Assert.NotNull(container.GetInstance()); + Assert.NotNull(container.GetInstance()); Assert.NotNull(container.GetInstance()); } @@ -93,6 +122,7 @@ public void RegisterDoesNotRequirePopulate() Assert.NotNull(container.GetInstance()); Assert.NotNull(container.GetInstance()); + Assert.NotNull(container.GetInstance()); Assert.NotNull(container.GetInstance()); }