Skip to content

Commit 2e6ead9

Browse files
Refactor: Enhance interface generation examples to improve clarity and align with domain-specific use cases
1 parent 7c03315 commit 2e6ead9

8 files changed

Lines changed: 96 additions & 140 deletions
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="Test examples with name" type="DotNetProject" factoryName=".NET Project" folderName="Targets">
3+
<option name="EXE_PATH" value="$PROJECT_DIR$/build/bin/Debug/net10.0/build.exe" />
4+
<option name="PROGRAM_PARAMETERS" value="&quot;-p:example=Customize the generated interface&quot; -- te" />
5+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
6+
<option name="PASS_PARENT_ENVS" value="1" />
7+
<option name="ENV_FILE_PATHS" value="" />
8+
<option name="REDIRECT_INPUT_PATH" value="" />
9+
<option name="MIXED_MODE_DEBUG" value="0" />
10+
<option name="USE_MONO" value="0" />
11+
<option name="RUNTIME_ARGUMENTS" value="" />
12+
<option name="AUTO_ATTACH_CHILDREN" value="0" />
13+
<option name="PROJECT_PATH" value="$PROJECT_DIR$/build/build.csproj" />
14+
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
15+
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
16+
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="0" />
17+
<option name="PROJECT_KIND" value="DotNetCore" />
18+
<option name="PROJECT_TFM" value="net10.0" />
19+
<method v="2">
20+
<option name="Build" />
21+
</method>
22+
</configuration>
23+
</component>

build/Core/Targets/CreateExamplesTarget.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class CreateExamplesTarget(
2828
"Attributes",
2929
"Interception",
3030
"Hints",
31+
"Interfaces",
3132
"Advanced",
3233
"UseCases",
3334
"Unity"

build/Core/Targets/TestExamplesTarget.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace Build.Core.Targets;
77
class TestExamplesTarget(
88
Commands commands,
99
Env env,
10+
Properties properties,
1011
[Tag(typeof(CreateExamplesTarget))] ITarget<IReadOnlyCollection<ExampleGroup>> createExamplesTarget)
1112
: IInitializable, ITarget<int>
1213
{
@@ -31,6 +32,7 @@ public async Task<int> RunAsync(CancellationToken cancellationToken)
3132
var appDir = Path.Combine(tempDir, "App");
3233
File.Copy(Path.Combine(solutionDir, "tests", "Pure.DI.UsageTests", "Test.props"), Path.Combine(appDir, "Directory.Build.props"));
3334
var programFile = Path.Combine(appDir, "Program.cs");
35+
var example = properties["example"];
3436
foreach (var (_, groupExamples) in examples)
3537
{
3638
foreach (var vars in groupExamples)
@@ -41,6 +43,12 @@ public async Task<int> RunAsync(CancellationToken cancellationToken)
4143
}
4244

4345
var description = vars[CreateExamplesTarget.DescriptionKey];
46+
if (!string.IsNullOrWhiteSpace(example)
47+
&& !string.Equals(example, description, StringComparison.InvariantCultureIgnoreCase))
48+
{
49+
continue;
50+
}
51+
4452
var code = vars[CreateExamplesTarget.BodyKey];
4553
await File.WriteAllTextAsync(programFile, code, cancellationToken);
4654
var result = new DotNetBuild()

tests/Pure.DI.UsageTests/Interface/GenerateInterfaceGenericTypeScenario.cs

Lines changed: 0 additions & 70 deletions
This file was deleted.

tests/Pure.DI.UsageTests/Interface/GenerateInterfaceCustomizationScenario.cs renamed to tests/Pure.DI.UsageTests/Interfaces/GenerateInterfaceCustomizationScenario.cs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
$v=true
33
$p=9
44
$d=Customize the generated interface
5-
$h=This example shows how to change the generated interface name, namespace, and accessibility.
5+
$h=This example shows how to place a generated contract in a dedicated Contracts namespace.
66
$f=The example shows how to:
77
$f=- Generate an interface into a custom namespace
88
$f=- Rename the generated interface
9-
$f=- Make the generated interface internal
10-
$r=Shouldly
9+
$f=- Keep the contract separate from implementation details
10+
$i=false
1111
*/
1212

1313
// ReSharper disable ClassNeverInstantiated.Global
@@ -17,23 +17,9 @@
1717

1818
using Pure.DI;
1919

20-
namespace Contracts
21-
{
22-
public partial interface IWorker;
23-
24-
[GenerateInterface(namespaceName: "Contracts", interfaceName: "IWorker")]
25-
public class Worker : IWorker
26-
{
27-
public string Message => "custom";
28-
}
29-
}
30-
31-
namespace Pure.DI.UsageTests.Interface.GenerateInterfaceCustomizationScenario
20+
namespace Pure.DI.UsageTests.Interfaces.GenerateInterfaceCustomizationScenario
3221
{
33-
using Pure.DI.UsageTests;
3422
using Contracts;
35-
using Pure.DI;
36-
using Shouldly;
3723
using Xunit;
3824

3925
// {
@@ -47,21 +33,36 @@ public void Run()
4733
{
4834
// {
4935
DI.Setup(nameof(Composition))
50-
.Bind().To<Worker>()
36+
.Bind<IInvoiceGenerator>().To<InvoiceGenerator>()
5137
.Root<App>(nameof(App));
5238

5339
var composition = new Composition();
5440
var app = composition.App;
5541

56-
app.Message.ShouldBe("custom");
42+
app.InvoiceId.ShouldBe("INV-0042");
5743
// }
5844

5945
composition.SaveClassDiagram();
6046
}
6147
}
6248

63-
public class App(IWorker worker)
49+
// {
50+
public class App(IInvoiceGenerator generator)
51+
{
52+
public string InvoiceId { get; } = generator.Format(42);
53+
}
54+
// }
55+
}
56+
57+
// {
58+
namespace Contracts
59+
{
60+
public partial interface IInvoiceGenerator;
61+
62+
[GenerateInterface(namespaceName: "Contracts", interfaceName: "IInvoiceGenerator")]
63+
public class InvoiceGenerator : IInvoiceGenerator
6464
{
65-
public string Message { get; } = worker.Message;
65+
public string Format(int number) => $"INV-{number:0000}";
6666
}
6767
}
68+
// }

tests/Pure.DI.UsageTests/Interface/GenerateInterfaceGenericsScenario.cs renamed to tests/Pure.DI.UsageTests/Interfaces/GenerateInterfaceGenericsScenario.cs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
$v=true
33
$p=9
44
$d=Generate interfaces with generics
5-
$h=This example shows that generic members, nullable annotations, and events are preserved in the generated interface.
5+
$h=This example shows how generic members, nullable annotations, and events are preserved in a reporting scenario.
66
$f=The example shows how to:
77
$f=- Generate an interface for generic members
88
$f=- Preserve nullable annotations
@@ -15,12 +15,9 @@
1515
// ReSharper disable UnusedType.Global
1616
// ReSharper disable UnusedMember.Global
1717

18-
namespace Pure.DI.UsageTests.Interface.GenerateInterfaceGenericsScenario;
18+
#pragma warning disable CS0067
19+
namespace Pure.DI.UsageTests.Interfaces.GenerateInterfaceGenericsScenario;
1920

20-
using System;
21-
using Pure.DI.UsageTests;
22-
using Pure.DI;
23-
using Shouldly;
2421
using Xunit;
2522

2623
// {
@@ -34,32 +31,29 @@ public void Run()
3431
{
3532
// {
3633
DI.Setup(nameof(Composition))
37-
.Bind().To<Formatter>()
38-
.Bind<App>().To<App>()
34+
.Bind<IReportFormatter>().To<ReportFormatter>()
3935
.Root<App>(nameof(App));
4036

4137
var composition = new Composition();
4238
var app = composition.App;
4339

44-
app.Formatted.ShouldBe("demo");
45-
app.Title.ShouldBe("demo");
40+
app.Formatted.ShouldBe("Order #42");
41+
app.Title.ShouldBe("Daily Report");
4642
// }
4743

4844
composition.SaveClassDiagram();
4945
}
5046
}
5147

5248
// {
53-
public partial interface IFormatter;
49+
public partial interface IReportFormatter;
5450

5551
[GenerateInterface]
56-
public class Formatter : IFormatter
52+
public class ReportFormatter : IReportFormatter
5753
{
58-
public string? Title { get; set; } = "demo";
54+
public string? Title { get; set; } = "Daily Report";
5955

60-
#pragma warning disable CS0067
6156
public event EventHandler? Changed;
62-
#pragma warning restore CS0067
6357

6458
public string? Format<T>(T value)
6559
where T : class
@@ -69,10 +63,15 @@ public class Formatter : IFormatter
6963
public void Hidden() { }
7064
}
7165

72-
public class App(IFormatter formatter)
66+
public class App(IReportFormatter formatter)
7367
{
7468
public string Title { get; } = formatter.Title ?? string.Empty;
7569

76-
public string Formatted { get; } = formatter.Format("demo") ?? string.Empty;
70+
public string Formatted { get; } = formatter.Format(new Order(42)) ?? string.Empty;
71+
}
72+
73+
public class Order(int id)
74+
{
75+
public override string ToString() => $"Order #{id}";
7776
}
7877
// }

tests/Pure.DI.UsageTests/Interface/GenerateInterfaceScenario.cs renamed to tests/Pure.DI.UsageTests/Interfaces/GenerateInterfaceScenario.cs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
$v=true
33
$p=9
44
$d=Generate an interface from a class
5-
$h=This example shows how a public class can generate a matching interface and be used through Pure.DI.
5+
$h=This example shows how a concrete service can generate a matching interface and be consumed through Pure.DI.
66
$f=The example shows how to:
77
$f=- Generate an interface from a class
88
$f=- Bind the generated contract in Pure.DI
9-
$f=- Resolve the consumer from a composition root
9+
$f=- Resolve a consumer that depends on the interface
1010
$r=Shouldly
1111
*/
1212

@@ -15,11 +15,8 @@
1515
// ReSharper disable UnusedType.Global
1616
// ReSharper disable UnusedMember.Global
1717

18-
namespace Pure.DI.UsageTests.Interface.GenerateInterfaceScenario;
18+
namespace Pure.DI.UsageTests.Interfaces.GenerateInterfaceScenario;
1919

20-
using Pure.DI.UsageTests;
21-
using Pure.DI;
22-
using Shouldly;
2320
using Xunit;
2421

2522
// {
@@ -33,35 +30,35 @@ public void Run()
3330
{
3431
// {
3532
DI.Setup(nameof(Composition))
36-
.Bind().To<Service>()
33+
.Bind().To<EmailSender>()
3734
.Root<App>(nameof(App));
3835

3936
var composition = new Composition();
4037
var app = composition.App;
4138

42-
app.Message.ShouldBe("ok");
43-
app.Text.ShouldBe("pong");
39+
app.Provider.ShouldBe("smtp");
40+
app.Result.ShouldBe("sent:ops@contoso.com");
4441
// }
4542

4643
composition.SaveClassDiagram();
4744
}
4845
}
4946

5047
// {
51-
public partial interface IService;
48+
public partial interface IEmailSender;
5249

5350
[GenerateInterface]
54-
public class Service : IService
51+
public class EmailSender : IEmailSender
5552
{
56-
public string Message => "ok";
53+
public string Provider => "smtp";
5754

58-
public string Ping() => "pong";
55+
public string Send(string address) => $"sent:{address}";
5956
}
6057

61-
public class App(IService service)
58+
public class App(IEmailSender sender)
6259
{
63-
public string Message { get; } = service.Message;
60+
public string Provider { get; } = sender.Provider;
6461

65-
public string Text { get; } = service.Ping();
62+
public string Result { get; } = sender.Send("ops@contoso.com");
6663
}
6764
// }

0 commit comments

Comments
 (0)