@@ -7137,6 +7137,192 @@ To run the above code, the following NuGet packages must be added:
71377137
71387138For more hints, see [ this] ( ../README.md#setup-hints ) page.
71397139
7140+ ## Customize the generated interface
7141+
7142+ This example shows how to place a generated contract in a dedicated Contracts namespace.
7143+
7144+ ``` c#
7145+ using Pure .DI ;
7146+
7147+ DI .Setup (nameof (Composition ))
7148+ .Bind ().To <InvoiceGenerator >()
7149+ .Root <App >(nameof (App ));
7150+
7151+ var composition = new Composition ();
7152+ var app = composition .App ;
7153+
7154+ app .InvoiceId .ShouldBe (" INV-0042" );
7155+
7156+ public class App (IMyInvoiceGenerator generator )
7157+ {
7158+ public string InvoiceId { get ; } = generator .Format (42 );
7159+ }
7160+
7161+ namespace Contracts
7162+ {
7163+ public partial interface IMyInvoiceGenerator ;
7164+
7165+ [GenerateInterface (namespaceName : " Contracts" , interfaceName : nameof (IMyInvoiceGenerator ))]
7166+ public class InvoiceGenerator : IMyInvoiceGenerator
7167+ {
7168+ public string Format (int number ) => $" INV-{number : 0000 }" ;
7169+ }
7170+ }
7171+ ```
7172+
7173+ To run the above code, the following NuGet package must be added:
7174+ - [ Pure.DI] ( https://www.nuget.org/packages/Pure.DI )
7175+
7176+ The example shows how to:
7177+ - Generate an interface into a custom namespace
7178+ - Rename the generated interface
7179+ - Keep the contract separate from implementation details
7180+
7181+ ## Generate an interface from a class
7182+
7183+ This example shows how a concrete service can generate a matching interface and be consumed through Pure.DI.
7184+
7185+ ``` c#
7186+ using Shouldly ;
7187+ using Pure .DI ;
7188+
7189+ DI .Setup (nameof (Composition ))
7190+ .Bind ().To <EmailSender >()
7191+ .Root <App >(nameof (App ));
7192+
7193+ var composition = new Composition ();
7194+ var app = composition .App ;
7195+
7196+ app .Provider .ShouldBe (" smtp" );
7197+ app .Result .ShouldBe (" sent:ops@contoso.com" );
7198+
7199+ public partial interface IEmailSender ;
7200+
7201+ [GenerateInterface ]
7202+ public class EmailSender : IEmailSender
7203+ {
7204+ public string Provider => " smtp" ;
7205+
7206+ public string Send (string address ) => $" sent:{address }" ;
7207+ }
7208+
7209+ public class App (IEmailSender sender )
7210+ {
7211+ public string Provider { get ; } = sender .Provider ;
7212+
7213+ public string Result { get ; } = sender .Send (" ops@contoso.com" );
7214+ }
7215+ ```
7216+
7217+ To run the above code, the following NuGet packages must be added:
7218+ - [ Pure.DI] ( https://www.nuget.org/packages/Pure.DI )
7219+ - [ Shouldly] ( https://www.nuget.org/packages/Shouldly )
7220+
7221+ The example shows how to:
7222+ - Generate an interface from a class
7223+ - Bind the generated contract in Pure.DI
7224+ - Resolve a consumer that depends on the interface
7225+
7226+ ## Generate interfaces with generics
7227+
7228+ This example shows how generic members, nullable annotations, and events are preserved in a reporting scenario.
7229+
7230+ ``` c#
7231+ using Shouldly ;
7232+ using Pure .DI ;
7233+
7234+ DI .Setup (nameof (Composition ))
7235+ .Bind ().To <ReportFormatter >()
7236+ .Root <App >(nameof (App ));
7237+
7238+ var composition = new Composition ();
7239+ var app = composition .App ;
7240+
7241+ app .Formatted .ShouldBe (" Order #42" );
7242+ app .Title .ShouldBe (" Daily Report" );
7243+
7244+ public partial interface IReportFormatter ;
7245+
7246+ [GenerateInterface ]
7247+ public class ReportFormatter : IReportFormatter
7248+ {
7249+ public string ? Title { get ; set ; } = " Daily Report" ;
7250+
7251+ public event EventHandler ? Changed ;
7252+
7253+ public string ? Format <T >(T value )
7254+ where T : class
7255+ => value ? .ToString ();
7256+
7257+ [IgnoreInterface ]
7258+ public void Hidden () { }
7259+ }
7260+
7261+ public class App (IReportFormatter formatter )
7262+ {
7263+ public string Title { get ; } = formatter .Title ?? string .Empty ;
7264+
7265+ public string Formatted { get ; } = formatter .Format (new Order (42 )) ?? string .Empty ;
7266+ }
7267+
7268+ public class Order (int id )
7269+ {
7270+ public override string ToString () => $" Order #{id }" ;
7271+ }
7272+ ```
7273+
7274+ To run the above code, the following NuGet packages must be added:
7275+ - [ Pure.DI] ( https://www.nuget.org/packages/Pure.DI )
7276+ - [ Shouldly] ( https://www.nuget.org/packages/Shouldly )
7277+
7278+ The example shows how to:
7279+ - Generate an interface for generic members
7280+ - Preserve nullable annotations
7281+ - Preserve events and generic constraints
7282+
7283+ ## Ignore members in the generated interface
7284+
7285+ This example shows how to exclude internal-only members from a generated interface.
7286+
7287+ ``` c#
7288+ using Shouldly ;
7289+ using Pure .DI ;
7290+
7291+ DI .Setup (nameof (Composition ))
7292+ .Bind ().To <ApiClient >()
7293+ .Root <App >(nameof (App ));
7294+
7295+ var composition = new Composition ();
7296+ var app = composition .App ;
7297+
7298+ app .Endpoint .ShouldBe (" https://api.contoso.com" );
7299+
7300+ public partial interface IApiClient ;
7301+
7302+ [GenerateInterface ]
7303+ public class ApiClient : IApiClient
7304+ {
7305+ public string Endpoint => " https://api.contoso.com" ;
7306+
7307+ [IgnoreInterface ]
7308+ public string GetAccessToken () => " internal-token" ;
7309+ }
7310+
7311+ public class App (IApiClient client )
7312+ {
7313+ public string Endpoint { get ; } = client .Endpoint ;
7314+ }
7315+ ```
7316+
7317+ To run the above code, the following NuGet packages must be added:
7318+ - [ Pure.DI] ( https://www.nuget.org/packages/Pure.DI )
7319+ - [ Shouldly] ( https://www.nuget.org/packages/Shouldly )
7320+
7321+ The example shows how to:
7322+ - Mark members with IgnoreInterface
7323+ - Keep only the intended contract surface
7324+ - Use the generated interface in Pure.DI
7325+
71407326## Composition root kinds
71417327
71427328Demonstrates different kinds of composition roots that can be created: public methods, private partial methods, and static roots. Each kind serves different use cases for accessing composition roots with appropriate visibility and lifetime semantics.
0 commit comments