Skip to content

Commit 1691597

Browse files
Name templates
1 parent 3744a92 commit 1691597

File tree

6 files changed

+438
-49
lines changed

6 files changed

+438
-49
lines changed

src/Pure.DI.Core/Components/Api.g.cs

Lines changed: 198 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ internal enum Hint
660660
OnCannotResolveLifetimeWildcard,
661661

662662
/// <summary>
663-
/// <c>On</c> or <c>Off</c>. Determines whether to use a static partial <c>OnNewRoot&lt;T&gt;(...)</c> method to handle the new Composition root registration event. <c>Off</c> by default.
663+
/// <c>On</c> or <c>Off</c>. Determines whether to use a static partial <c>OnNewRoot&lt;T&gt;(...)</c> method to handle the new composition root registration event. <c>Off</c> by default.
664664
/// <example>
665665
/// <code>
666666
/// // OnNewRoot = On
@@ -680,7 +680,7 @@ internal enum Hint
680680
OnNewRoot,
681681

682682
/// <summary>
683-
/// <c>On</c> or <c>Off</c>. Determines whether to generate a static partial <c>OnNewRoot&lt;T&gt;(...)</c> method when the <c>OnNewRoot</c> hint is <c>On</c> to handle the new Composition root registration event. <c>On</c> by default.
683+
/// <c>On</c> or <c>Off</c>. Determines whether to generate a static partial <c>OnNewRoot&lt;T&gt;(...)</c> method when the <c>OnNewRoot</c> hint is <c>On</c> to handle the new composition root registration event. <c>On</c> by default.
684684
/// <example>
685685
/// <code>
686686
/// // OnNewRootPartial = On
@@ -720,7 +720,7 @@ internal enum Hint
720720
ToString,
721721

722722
/// <summary>
723-
/// <c>On</c> or <c>Off</c>. This hint determines whether object Composition will be created in a thread-safe manner. <c>On</c> by default.
723+
/// <c>On</c> or <c>Off</c>. This hint determines whether object composition will be created in a thread-safe manner. <c>On</c> by default.
724724
/// <example>
725725
/// <code>
726726
/// // ThreadSafe = Off
@@ -1879,8 +1879,31 @@ internal interface IConfiguration
18791879
/// </example>
18801880
/// </summary>
18811881
/// <typeparam name="T">The type of dependency to be bound.</typeparam>
1882-
/// <param name="name">Specifies the name template of the root of the composition. If the value is empty, a private root will be created, which can be used when calling <c>Resolve</c> methods.</param>
1883-
/// <param name="kind">The Optional argument specifying the kind for the root of the Composition.</param>
1882+
/// <param name="name">
1883+
/// Specifies the name of the root of the composition. If the value is empty, a private root will be created, which can be used when calling <c>Resolve</c> methods.
1884+
/// <para>
1885+
/// The name supports templating:
1886+
/// <list type="table">
1887+
/// <listheader>
1888+
/// <term>Template</term>
1889+
/// <description>Description</description>
1890+
/// </listheader>
1891+
/// <item>
1892+
/// <term>{type}</term>
1893+
/// <description>Will be replaced by the short name of the root type without its namespaces.</description>
1894+
/// </item>
1895+
/// <item>
1896+
/// <term>{TYPE}</term>
1897+
/// <description>Will be replaced with the full name of the root type.</description>
1898+
/// </item>
1899+
/// <item>
1900+
/// <term>{tag}</term>
1901+
/// <description>Will be replaced with the first tag name.</description>
1902+
/// </item>
1903+
/// </list>
1904+
/// </para>
1905+
/// </param>
1906+
/// <param name="kind">The optional argument specifying the kind for the root of the composition.</param>
18841907
/// <param name="tags">The optional argument that specifies tags for a particular type of dependency binding. If is is not empty, the first tag is used for the root.</param>
18851908
/// <returns>Reference to the setup continuation chain.</returns>
18861909
/// <seealso cref="To{T}()"/>
@@ -2000,7 +2023,7 @@ internal interface IConfiguration
20002023
/// </example>
20012024
/// </summary>
20022025
/// <param name="lifetime">The default lifetime.</param>
2003-
/// <param name="tags">Optional argument specifying the binding tags for which it will set the default lifetime. If not specified, the default lifetime will be set for any tags.</param>
2026+
/// <param name="tags">The optional argument specifying the binding tags for which it will set the default lifetime. If not specified, the default lifetime will be set for any tags.</param>
20042027
/// <typeparam name="T">The default lifetime will be applied to bindings if the implementation class can be cast to type <typeparamref name="T"/>.</typeparam>
20052028
/// <returns>Reference to the setup continuation chain.</returns>
20062029
/// <seealso cref="Lifetime"/>
@@ -2016,7 +2039,30 @@ internal interface IConfiguration
20162039
/// </code>
20172040
/// </example>
20182041
/// </summary>
2019-
/// <param name="name">The argument name template.</param>
2042+
/// <param name="name">
2043+
/// The argument name.
2044+
/// <para>
2045+
/// The name supports templating:
2046+
/// <list type="table">
2047+
/// <listheader>
2048+
/// <term>Template</term>
2049+
/// <description>Description</description>
2050+
/// </listheader>
2051+
/// <item>
2052+
/// <term>{type}</term>
2053+
/// <description>Will be replaced by the short name of the argument type without its namespaces.</description>
2054+
/// </item>
2055+
/// <item>
2056+
/// <term>{TYPE}</term>
2057+
/// <description>Will be replaced with the full name of the argument type.</description>
2058+
/// </item>
2059+
/// <item>
2060+
/// <term>{tag}</term>
2061+
/// <description>Will be replaced with the first tag name.</description>
2062+
/// </item>
2063+
/// </list>
2064+
/// </para>
2065+
/// </param>
20202066
/// <param name="tags">The optional argument that specifies the tags for the argument.</param>
20212067
/// <typeparam name="T">The argument type.</typeparam>
20222068
/// <returns>Reference to the setup continuation chain.</returns>
@@ -2031,40 +2077,117 @@ internal interface IConfiguration
20312077
/// </code>
20322078
/// </example>
20332079
/// </summary>
2034-
/// <param name="name">The argument name tamplate.</param>
2080+
/// <param name="name">
2081+
/// The argument name.
2082+
/// <para>
2083+
/// The name supports templating:
2084+
/// <list type="table">
2085+
/// <listheader>
2086+
/// <term>Template</term>
2087+
/// <description>Description</description>
2088+
/// </listheader>
2089+
/// <item>
2090+
/// <term>{type}</term>
2091+
/// <description>Will be replaced by the short name of the argument type without its namespaces.</description>
2092+
/// </item>
2093+
/// <item>
2094+
/// <term>{TYPE}</term>
2095+
/// <description>Will be replaced with the full name of the argument type.</description>
2096+
/// </item>
2097+
/// <item>
2098+
/// <term>{tag}</term>
2099+
/// <description>Will be replaced with the first tag name.</description>
2100+
/// </item>
2101+
/// </list>
2102+
/// </para>
2103+
/// </param>
20352104
/// <param name="tags">The optional argument that specifies the tags for the argument.</param>
20362105
/// <typeparam name="T">The argument type.</typeparam>
20372106
/// <returns>Reference to the setup continuation chain.</returns>
20382107
IConfiguration RootArg<T>(string name, params object[] tags);
20392108

20402109
/// <summary>
2041-
/// Specifying the root of the Composition.
2110+
/// Specifying the root of the composition.
20422111
/// <example>
20432112
/// <code>
20442113
/// DI.Setup("Composition")
20452114
/// .Root&lt;Service&gt;("MyService");
20462115
/// </code>
20472116
/// </example>
2117+
/// <example>
2118+
/// <code>
2119+
/// DI.Setup("Composition")
2120+
/// .Root&lt;Service&gt;("My{type}");
2121+
/// </code>
2122+
/// </example>
20482123
/// </summary>
2049-
/// <param name="name">Specifies the name template of the root of the composition. If the value is empty, a private root will be created, which can be used when calling <c>Resolve</c> methods.</param>
2050-
/// <param name="tag">Optional argument specifying the tag for the root of the Composition.</param>
2051-
/// <param name="kind">The Optional argument specifying the kind for the root of the Composition.</param>
2052-
/// <typeparam name="T">The Composition root type.</typeparam>
2124+
/// <param name="name">
2125+
/// Specifies the name of the root of the composition. If the value is empty, a private root will be created, which can be used when calling <c>Resolve</c> methods.
2126+
/// <para>
2127+
/// The name supports templating:
2128+
/// <list type="table">
2129+
/// <listheader>
2130+
/// <term>Template</term>
2131+
/// <description>Description</description>
2132+
/// </listheader>
2133+
/// <item>
2134+
/// <term>{type}</term>
2135+
/// <description>Will be replaced by the short name of the root type without its namespaces.</description>
2136+
/// </item>
2137+
/// <item>
2138+
/// <term>{TYPE}</term>
2139+
/// <description>Will be replaced with the full name of the root type.</description>
2140+
/// </item>
2141+
/// <item>
2142+
/// <term>{tag}</term>
2143+
/// <description>Will be replaced with the root tag name.</description>
2144+
/// </item>
2145+
/// </list>
2146+
/// </para>
2147+
/// </param>
2148+
/// <param name="tag">The optional argument specifying the tag for the root of the composition.</param>
2149+
/// <param name="kind">The optional argument specifying the kind for the root of the composition.</param>
2150+
/// <typeparam name="T">The composition root type.</typeparam>
20532151
/// <returns>Reference to the setup continuation chain.</returns>
20542152
IConfiguration Root<T>(string name = "", object tag = null, RootKinds kind = RootKinds.Default);
20552153

20562154
/// <summary>
2057-
/// Specifying the roots of the Composition.
2155+
/// Specifies to define composition roots for all types inherited from <see cref="T"/> available at compile time at the time this method is called.
20582156
/// <example>
20592157
/// <code>
20602158
/// DI.Setup("Composition")
20612159
/// .Roots&lt;IService&gt;();
20622160
/// </code>
20632161
/// </example>
2162+
/// <example>
2163+
/// <code>
2164+
/// DI.Setup("Composition")
2165+
/// .Roots&lt;IService&gt;("Root{type}");
2166+
/// </code>
2167+
/// </example>
20642168
/// </summary>
2065-
/// <param name="name">Specifies the name template of the roots of the composition. If the value is empty, private roots will be created, which can be used when calling <c>Resolve</c> methods.</param>
2066-
/// <param name="kind">The Optional argument specifying the kind for the root of the Composition.</param>
2067-
/// <typeparam name="T">The Composition root base type.</typeparam>
2169+
/// <param name="name">
2170+
/// Specifies the name of the roots of the composition. If the value is empty, private roots will be created, which can be used when calling <c>Resolve</c> methods.
2171+
/// <para>
2172+
/// The name supports templating:
2173+
/// <list type="table">
2174+
/// <listheader>
2175+
/// <term>Template</term>
2176+
/// <description>Description</description>
2177+
/// </listheader>
2178+
/// <item>
2179+
/// <term>{type}</term>
2180+
/// <description>Will be replaced by the short name of the type without its namespaces.</description>
2181+
/// </item>
2182+
/// <item>
2183+
/// <term>{TYPE}</term>
2184+
/// <description>Will be replaced with the full name of the type.</description>
2185+
/// </item>
2186+
/// </list>
2187+
/// </para>
2188+
/// </param>
2189+
/// <param name="kind">The optional argument specifying the kind for the root of the composition.</param>
2190+
/// <typeparam name="T">The composition root base type.</typeparam>
20682191
/// <returns>Reference to the setup continuation chain.</returns>
20692192
IConfiguration Roots<T>(string name = "", RootKinds kind = RootKinds.Default);
20702193

@@ -2077,24 +2200,74 @@ internal interface IConfiguration
20772200
/// </code>
20782201
/// </example>
20792202
/// </summary>
2080-
/// <param name="name">Specifies the name template of the builder. The default name tamplate is "BuildUp".</param>
2081-
/// <param name="kind">The Optional argument specifying the kind for the root of the Composition.</param>
2082-
/// <typeparam name="T">The Composition root type.</typeparam>
2203+
/// <param name="name">
2204+
/// Specifies the name of the builder. The default name is "BuildUp".
2205+
/// <para>
2206+
/// The name supports templating:
2207+
/// <list type="table">
2208+
/// <listheader>
2209+
/// <term>Template</term>
2210+
/// <description>Description</description>
2211+
/// </listheader>
2212+
/// <item>
2213+
/// <term>{type}</term>
2214+
/// <description>Will be replaced by the short name of the type without its namespaces.</description>
2215+
/// </item>
2216+
/// <item>
2217+
/// <term>{TYPE}</term>
2218+
/// <description>Will be replaced with the full name of the type.</description>
2219+
/// </item>
2220+
/// </list>
2221+
/// </para>
2222+
/// </param>
2223+
/// <param name="kind">The optional argument specifying the kind for the root of the composition.</param>
2224+
/// <typeparam name="T">The composition root type.</typeparam>
20832225
/// <returns>Reference to the setup continuation chain.</returns>
20842226
IConfiguration Builder<T>(string name = "BuildUp", RootKinds kind = RootKinds.Default);
20852227

20862228
/// <summary>
2087-
/// Specifies the methods of the composition builders. The first argument to the method will always be the instance to be built. The remaining arguments to this method will be listed in the order in which they are defined in the setup.Specifies to create a composition builder method. The first argument to the method will always be the instance to be built. The remaining arguments to this method will be listed in the order in which they are defined in the setup.
2229+
/// Specifies to define builders for all types inherited from <see cref="T"/> available at compile time at the time this method is called.
20882230
/// <example>
20892231
/// <code>
20902232
/// DI.Setup("Composition")
2091-
/// .Builder&lt;Service&gt;("BuildUpMyService");
2233+
/// .Builders&lt;Service&gt;();
2234+
/// </code>
2235+
/// </example>
2236+
/// <example>
2237+
/// <code>
2238+
/// DI.Setup("Composition")
2239+
/// .Builder&lt;Service&gt;("BuildUp");
2240+
/// </code>
2241+
/// </example>
2242+
/// <example>
2243+
/// <code>
2244+
/// DI.Setup("Composition")
2245+
/// .Builder&lt;Service&gt;("BuildUp{type}");
20922246
/// </code>
20932247
/// </example>
20942248
/// </summary>
2095-
/// <param name="name">Specifies the name template of the builders. The default name tamplate is "BuildUp".</param>
2096-
/// <param name="kind">The Optional argument specifying the kind for the root of the Composition.</param>
2097-
/// <typeparam name="T">The Composition root base type.</typeparam>
2249+
/// <param name="name">
2250+
/// Specifies the name of the builders. The default name is "BuildUp".
2251+
/// <para>
2252+
/// The name supports templating:
2253+
/// <list type="table">
2254+
/// <listheader>
2255+
/// <term>Template</term>
2256+
/// <description>Description</description>
2257+
/// </listheader>
2258+
/// <item>
2259+
/// <term>{type}</term>
2260+
/// <description>Will be replaced by the short name of the type without its namespaces.</description>
2261+
/// </item>
2262+
/// <item>
2263+
/// <term>{TYPE}</term>
2264+
/// <description>Will be replaced with the full name of the type.</description>
2265+
/// </item>
2266+
/// </list>
2267+
/// </para>
2268+
/// </param>
2269+
/// <param name="kind">The optional argument specifying the kind for the root of the composition.</param>
2270+
/// <typeparam name="T">The composition root base type.</typeparam>
20982271
/// <returns>Reference to the setup continuation chain.</returns>
20992272
IConfiguration Builders<T>(string name = "BuildUp", RootKinds kind = RootKinds.Default);
21002273

src/Pure.DI.Core/Core/ApiInvocationProcessor.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -674,9 +674,15 @@ private void VisitArg(
674674
if (genericName.TypeArgumentList.Arguments is [{ } argTypeSyntax]
675675
&& invocation.ArgumentList.Arguments is [{ Expression: { } nameArgExpression }, ..] args)
676676
{
677-
var name = semantic.GetRequiredConstantValue<string>(semanticModel, nameArgExpression).Trim();
677+
var argType = semantic.GetTypeSymbol<INamedTypeSymbol>(semanticModel, argTypeSyntax);
678678
var tags = BuildTags(semanticModel, args.Skip(1));
679-
var argType = semantic.GetTypeSymbol<ITypeSymbol>(semanticModel, argTypeSyntax);
679+
var name = GetName(
680+
nameArgExpression,
681+
semanticModel,
682+
semantic.GetRequiredConstantValue<string>(semanticModel, nameArgExpression),
683+
argType,
684+
tags.IsEmpty ? null : tags[0].Value) ?? "";
685+
680686
metadataVisitor.VisitContract(new MdContract(semanticModel, invocation, argType, ContractKind.Explicit, tags.ToImmutableArray()));
681687
metadataVisitor.VisitArg(new MdArg(semanticModel, argTypeSyntax, argType, name, kind, false, argComments));
682688
}
@@ -935,12 +941,7 @@ private static CompositionName CreateCompositionName(
935941
return nameTemplate;
936942
}
937943

938-
var name = nameFormatter.Format(semanticModel, nameTemplate, type, tag);
939-
if (string.IsNullOrWhiteSpace(name))
940-
{
941-
return name;
942-
}
943-
944+
var name = nameFormatter.Format(semanticModel, nameTemplate!, type, tag);
944945
if (!SyntaxFacts.IsValidIdentifier(name))
945946
{
946947
throw new CompileErrorException($"Invalid identifier \"{name}\".", source.GetLocation(), LogId.ErrorInvalidMetadata);

src/Pure.DI.Core/Core/INameFormatter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
internal interface INameFormatter
44
{
5-
string? Format(
5+
string Format(
66
SemanticModel semanticModel,
7-
string? nameTemplate,
7+
string nameTemplate,
88
INamedTypeSymbol? type,
99
object? tag);
1010
}

0 commit comments

Comments
 (0)