Skip to content

Commit 3840dfd

Browse files
committed
added the initial test for the #678
1 parent d9a1889 commit 3840dfd

File tree

4 files changed

+143
-3
lines changed

4 files changed

+143
-3
lines changed

src/DryIoc.Microsoft.DependencyInjection/DryIocAdapter.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public static class DryIocAdapter
157157
theKey = Registrator.AnyKey;
158158

159159
return ParameterServiceInfo.Of(par, ServiceDetails.OfServiceKey(theKey));
160-
};
160+
}
161161

162162
return null;
163163
};
@@ -311,6 +311,10 @@ public static IServiceProvider GetServiceProvider(this IContainer container) =>
311311
public static IServiceProvider ConfigureServiceProvider<TCompositionRoot>(this IContainer container) =>
312312
container.WithCompositionRoot<TCompositionRoot>().GetServiceProvider();
313313

314+
/// <summary>Facade to consolidate DryIoc registrations in <typeparamref name="TCompositionRoot"/></summary>
315+
public static IServiceProvider ConfigureServiceProvider<TCompositionRoot>(this DryIocServiceProvider serviceProvider) =>
316+
serviceProvider.Container.WithCompositionRoot<TCompositionRoot>().GetServiceProvider();
317+
314318
/// <summary>Registers service descriptors into container. May be called multiple times with different service collections.</summary>
315319
/// <param name="container">The container.</param>
316320
/// <param name="descriptors">The service descriptors.</param>

test/DryIoc.IssuesTests/DryIoc.IssuesTests.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
<PackageReference Include="Castle.Core" Version="5.1.1" />
1313
<PackageReference Include="MediatR" Version="9.0.0" />
1414
<PackageReference Include="NSubstitute" Version="5.1.0" />
15-
<PackageReference Include="Moq" Version="4.20.70" />
15+
<PackageReference Include="Moq" Version="4.20.72" />
1616
<PackageReference Include="log4net" Version="2.0.15" />
17+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.2" />
1718
</ItemGroup>
1819

1920
<ItemGroup>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
using NUnit.Framework;
2+
using System;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.Extensions.Hosting;
5+
using DryIoc.Microsoft.DependencyInjection;
6+
7+
namespace DryIoc.IssuesTests;
8+
9+
[TestFixture]
10+
public class GHIssue678_Scope_is_lost_in_diposable_service : ITest
11+
{
12+
public int Run()
13+
{
14+
Original_case();
15+
return 1;
16+
}
17+
18+
[Test]
19+
public void Original_case()
20+
{
21+
IServiceProvider serviceProvider = null;
22+
23+
var host = Host.CreateDefaultBuilder()
24+
.ConfigureServices(services =>
25+
{
26+
serviceProvider = new Container(
27+
// NOTE: You don't need to specify the rules here,
28+
// because this rule is the part of `WithDependencyInjectionAdapter` configuration
29+
//
30+
// rules => rules.With(FactoryMethod.ConstructorWithResolvableArguments)
31+
)
32+
.WithDependencyInjectionAdapter(services)
33+
// NOTE: you need this line (for now) to obtain the Container from the DryIocServiceProvider
34+
// in the DryIoc.MS.DI v8.0.0-preview-04.
35+
// I will add the new ConfigureServiceProvider overload for the DryIocServiceProvider into the later version,
36+
// so you don't need to change your code.
37+
.Container
38+
.ConfigureServiceProvider<CompositionRoot>();
39+
})
40+
.Build();
41+
42+
using var scope = serviceProvider.CreateScope();
43+
44+
var service = scope.ServiceProvider.GetRequiredService<ServiceA>();
45+
service.Do();
46+
}
47+
48+
public class CompositionRoot
49+
{
50+
public CompositionRoot(IRegistrator registrator)
51+
{
52+
registrator.Register<Context>(reuse: Reuse.Scoped);
53+
registrator.Register<Strategy>();
54+
registrator.Register<ServiceC<Strategy>>();
55+
registrator.Register<ServiceB>();
56+
registrator.Register<ServiceA>();
57+
}
58+
}
59+
60+
public class Context
61+
{
62+
public string Value { get; set; }
63+
}
64+
65+
public class Strategy
66+
{
67+
public Strategy(Context context, IResolver resolver)
68+
{
69+
var resolvedContext = resolver.Resolve<Context>();
70+
}
71+
}
72+
73+
public class ServiceC<TContext> : IDisposable
74+
{
75+
public ServiceC(Strategy strategy, Context context)
76+
{
77+
}
78+
79+
public void Dispose()
80+
{
81+
}
82+
}
83+
84+
public class ServiceB
85+
{
86+
private readonly IContainer _container;
87+
private readonly Context _context;
88+
89+
public ServiceB(IContainer container, Context context)
90+
{
91+
_container = container;
92+
_context = context;
93+
}
94+
95+
public void Do()
96+
{
97+
using var scope = _container.OpenScope();
98+
scope.Use(_context);
99+
100+
var context = scope.Resolve<Context>();
101+
102+
// here context.value is "value"
103+
var anotherContext = scope.Resolve<Strategy>();
104+
105+
// here context.value is null
106+
// here resolvedContext.value is "value" - resolvedContext is resolved from injected IResolver
107+
using var serviceC = scope.Resolve<ServiceC<Strategy>>();
108+
}
109+
}
110+
111+
public class ServiceA
112+
{
113+
private readonly IContainer _container;
114+
private readonly Context _context;
115+
private readonly ServiceB _serviceB;
116+
117+
public ServiceA(IContainer container, Context context, ServiceB serviceB)
118+
{
119+
_container = container;
120+
_context = context;
121+
_serviceB = serviceB;
122+
}
123+
124+
public void Do()
125+
{
126+
using var serviceC = _container.Resolve<ServiceC<Strategy>>(); // this cause the issue, please comment this line to resolve problem
127+
128+
_context.Value = "value";
129+
130+
_serviceB.Do();
131+
}
132+
}
133+
}

test/DryIoc.TestRunner/Program.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ public class Program
99
{
1010
public static void Main()
1111
{
12-
new RegisterAttributeTests().Run();
12+
new GHIssue678_Scope_is_lost_in_diposable_service().Run();
13+
14+
// new RegisterAttributeTests().Run();
1315

1416
// new RulesTests().Run();
1517

0 commit comments

Comments
 (0)