@@ -133,6 +133,319 @@ public static void Main()
133133 result . Warnings . Count ( i => i . Id == LogId . WarningInstanceMemberInDependsOnSetup ) . ShouldBe ( 1 , result ) ;
134134 }
135135
136+ [ Fact ]
137+ public async Task ShouldSupportArgumentSetupContextWithScopeMethod ( )
138+ {
139+ // Given
140+
141+ // When
142+ var result = await """
143+ using System;
144+ using Pure.DI;
145+
146+ namespace Sample
147+ {
148+ internal partial class BaseComposition
149+ {
150+ internal int Value { get; set; }
151+
152+ private void Setup()
153+ {
154+ DI.Setup(nameof(BaseComposition), CompositionKind.Internal)
155+ .Bind<int>().To(_ => Value);
156+ }
157+ }
158+
159+ internal partial class Composition
160+ {
161+ private void Setup()
162+ {
163+ DI.Setup(nameof(Composition))
164+ .Hint(Hint.ScopeMethodName, "SetupScope")
165+ .DependsOn(nameof(BaseComposition), SetupContextKind.Argument, "baseContext")
166+ .Bind<IService>().As(Lifetime.Scoped).To<Service>()
167+ .Root<IService>("Service");
168+ }
169+ }
170+
171+ interface IService
172+ {
173+ int Value { get; }
174+ }
175+
176+ sealed class Service : IService
177+ {
178+ public Service(int value)
179+ {
180+ Value = value;
181+ }
182+
183+ public int Value { get; }
184+ }
185+
186+ public class Program
187+ {
188+ public static void Main()
189+ {
190+ var baseContext = new BaseComposition { Value = 41 };
191+ var composition = new Composition(baseContext);
192+ Console.WriteLine(composition.Service.Value);
193+
194+ var scope = Composition.SetupScope(composition, new Composition(baseContext));
195+ Console.WriteLine(scope.Service.Value);
196+ }
197+ }
198+ }
199+ """ . RunAsync ( new Options ( LanguageVersion : LanguageVersion . CSharp9 ) ) ;
200+
201+ // Then
202+ result . Success . ShouldBeTrue ( result ) ;
203+ result . Errors . Count . ShouldBe ( 0 , result ) ;
204+ result . Warnings . Count . ShouldBe ( 0 , result ) ;
205+ result . StdOut . ShouldBe ( [ "41" , "41" ] , result ) ;
206+ }
207+
208+ [ Fact ]
209+ public async Task ShouldSupportArgumentSetupContextWithNestedScopeMethod ( )
210+ {
211+ // Given
212+
213+ // When
214+ var result = await """
215+ using System;
216+ using Pure.DI;
217+
218+ namespace Sample
219+ {
220+ internal partial class BaseComposition
221+ {
222+ internal int Value { get; set; }
223+
224+ private void Setup()
225+ {
226+ DI.Setup(nameof(BaseComposition), CompositionKind.Internal)
227+ .Bind<int>().To(_ => Value);
228+ }
229+ }
230+
231+ internal partial class Composition
232+ {
233+ private void Setup()
234+ {
235+ DI.Setup(nameof(Composition))
236+ .Hint(Hint.ScopeMethodName, "SetupScope")
237+ .DependsOn(nameof(BaseComposition), SetupContextKind.Argument, "baseContext")
238+ .Bind<IService>().As(Lifetime.Scoped).To<Service>()
239+ .Root<IService>("Service");
240+ }
241+ }
242+
243+ interface IService
244+ {
245+ int Value { get; }
246+ }
247+
248+ sealed class Service : IService
249+ {
250+ public Service(int value)
251+ {
252+ Value = value;
253+ }
254+
255+ public int Value { get; }
256+ }
257+
258+ public class Program
259+ {
260+ public static void Main()
261+ {
262+ var baseContext = new BaseComposition { Value = 41 };
263+ var composition = new Composition(baseContext);
264+ var scope1 = Composition.SetupScope(composition, new Composition(baseContext));
265+ Console.WriteLine(scope1.Service.Value);
266+
267+ var scope2 = Composition.SetupScope(scope1, new Composition(baseContext));
268+ Console.WriteLine(scope2.Service.Value);
269+ }
270+ }
271+ }
272+ """ . RunAsync ( new Options ( LanguageVersion : LanguageVersion . CSharp9 ) ) ;
273+
274+ // Then
275+ result . Success . ShouldBeTrue ( result ) ;
276+ result . Errors . Count . ShouldBe ( 0 , result ) ;
277+ result . Warnings . Count . ShouldBe ( 0 , result ) ;
278+ result . StdOut . ShouldBe ( [ "41" , "41" ] , result ) ;
279+ }
280+
281+ [ Fact ]
282+ public async Task ShouldSupportArgumentSetupContextWithScopeMethodAndCompositionArguments ( )
283+ {
284+ // Given
285+
286+ // When
287+ var result = await """
288+ using System;
289+ using Pure.DI;
290+
291+ namespace Sample
292+ {
293+ internal partial class BaseComposition
294+ {
295+ internal int Value { get; set; }
296+
297+ private void Setup()
298+ {
299+ DI.Setup(nameof(BaseComposition), CompositionKind.Internal)
300+ .Bind<int>().To(_ => Value);
301+ }
302+ }
303+
304+ interface IService
305+ {
306+ string Message { get; }
307+ }
308+
309+ sealed class Service : IService
310+ {
311+ public Service(int value, string tenant)
312+ {
313+ Message = $"{tenant}:{value}";
314+ }
315+
316+ public string Message { get; }
317+ }
318+
319+ internal partial class Composition
320+ {
321+ private void Setup()
322+ {
323+ DI.Setup(nameof(Composition))
324+ .Hint(Hint.ScopeMethodName, "SetupScope")
325+ .Arg<string>("tenant")
326+ .DependsOn(nameof(BaseComposition), SetupContextKind.Argument, "baseContext")
327+ .Bind<IService>().As(Lifetime.Scoped).To<Service>()
328+ .Root<IService>("Service");
329+ }
330+ }
331+
332+ public class Program
333+ {
334+ public static void Main()
335+ {
336+ var baseContext = new BaseComposition { Value = 41 };
337+ var composition = new Composition(tenant: "EU", baseContext: baseContext);
338+ Console.WriteLine(composition.Service.Message);
339+
340+ var scope = Composition.SetupScope(
341+ composition,
342+ new Composition(tenant: "EU", baseContext: baseContext));
343+ Console.WriteLine(scope.Service.Message);
344+ }
345+ }
346+ }
347+ """ . RunAsync ( new Options ( LanguageVersion : LanguageVersion . CSharp9 ) ) ;
348+
349+ // Then
350+ result . Success . ShouldBeTrue ( result ) ;
351+ result . Errors . Count . ShouldBe ( 0 , result ) ;
352+ result . Warnings . Count . ShouldBe ( 0 , result ) ;
353+ result . StdOut . ShouldBe ( [ "EU:41" , "EU:41" ] , result ) ;
354+ }
355+
356+ [ Fact ]
357+ public async Task ShouldSupportArgumentSetupContextWithScopeMethodAndSingleton ( )
358+ {
359+ // Given
360+
361+ // When
362+ var result = await """
363+ using System;
364+ using Pure.DI;
365+
366+ namespace Sample
367+ {
368+ internal partial class BaseComposition
369+ {
370+ internal int Value { get; set; }
371+
372+ private void Setup()
373+ {
374+ DI.Setup(nameof(BaseComposition), CompositionKind.Internal)
375+ .Bind<int>().To(_ => Value);
376+ }
377+ }
378+
379+ interface ISingletonService
380+ {
381+ int Value { get; }
382+ }
383+
384+ sealed class SingletonService : ISingletonService
385+ {
386+ public SingletonService(int value)
387+ {
388+ Value = value;
389+ }
390+
391+ public int Value { get; }
392+ }
393+
394+ interface IService
395+ {
396+ ISingletonService Singleton { get; }
397+ }
398+
399+ sealed class Service : IService
400+ {
401+ public Service(ISingletonService singleton)
402+ {
403+ Singleton = singleton;
404+ }
405+
406+ public ISingletonService Singleton { get; }
407+ }
408+
409+ internal partial class Composition
410+ {
411+ private void Setup()
412+ {
413+ DI.Setup(nameof(Composition))
414+ .Hint(Hint.ScopeMethodName, "SetupScope")
415+ .DependsOn(nameof(BaseComposition), SetupContextKind.Argument, "baseContext")
416+ .Bind<ISingletonService>().As(Lifetime.Singleton).To<SingletonService>()
417+ .Bind<IService>().As(Lifetime.Scoped).To<Service>()
418+ .Root<IService>("Service");
419+ }
420+ }
421+
422+ public class Program
423+ {
424+ public static void Main()
425+ {
426+ var baseContext = new BaseComposition { Value = 41 };
427+ var composition = new Composition(baseContext);
428+ var rootSingleton = composition.Service.Singleton;
429+ Console.WriteLine(rootSingleton.Value);
430+
431+ var scope = Composition.SetupScope(composition, new Composition(baseContext));
432+ var scopeSingleton1 = scope.Service.Singleton;
433+ var scopeSingleton2 = scope.Service.Singleton;
434+ Console.WriteLine(scopeSingleton1.Value);
435+ Console.WriteLine(rootSingleton == scopeSingleton1);
436+ Console.WriteLine(scopeSingleton1 == scopeSingleton2);
437+ }
438+ }
439+ }
440+ """ . RunAsync ( new Options ( LanguageVersion : LanguageVersion . CSharp9 ) ) ;
441+
442+ // Then
443+ result . Success . ShouldBeTrue ( result ) ;
444+ result . Errors . Count . ShouldBe ( 0 , result ) ;
445+ result . Warnings . Count . ShouldBe ( 0 , result ) ;
446+ result . StdOut . ShouldBe ( [ "41" , "41" , "True" , "True" ] , result ) ;
447+ }
448+
136449 [ Fact ]
137450 public async Task ShouldSupportRootArgumentWithSimpleFactory ( )
138451 {
0 commit comments