diff --git a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Metrics.RestClient.cs b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Metrics.RestClient.cs
index 31dd56da2b8..371d027f6b7 100644
--- a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Metrics.RestClient.cs
+++ b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Metrics.RestClient.cs
@@ -17,7 +17,9 @@ internal PipelineMessage CreateGetWidgetMetricsRequest(string day, RequestOption
{
ClientUriBuilder uri = new ClientUriBuilder();
uri.Reset(_endpoint);
- uri.AppendPath("/metrics/widgets/daysOfWeek/", false);
+ uri.AppendPath("/metrics/", false);
+ uri.AppendPath(_metricsNamespace, true);
+ uri.AppendPath("/widgets/daysOfWeek/", false);
uri.AppendPath(day, true);
PipelineMessage message = Pipeline.CreateMessage(uri.ToUri(), "GET", PipelineMessageClassifier200);
PipelineRequest request = message.Request;
diff --git a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Metrics.cs b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Metrics.cs
index 30284cdba24..65e1ea56883 100644
--- a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Metrics.cs
+++ b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Metrics.cs
@@ -14,6 +14,7 @@ namespace SampleTypeSpec
public partial class Metrics
{
private readonly Uri _endpoint;
+ private readonly string _metricsNamespace;
/// Initializes a new instance of Metrics for mocking.
protected Metrics()
@@ -23,30 +24,38 @@ protected Metrics()
/// Initializes a new instance of Metrics.
/// The HTTP pipeline for sending and receiving REST requests and responses.
/// Service endpoint.
- internal Metrics(ClientPipeline pipeline, Uri endpoint)
+ ///
+ internal Metrics(ClientPipeline pipeline, Uri endpoint, string metricsNamespace)
{
_endpoint = endpoint;
Pipeline = pipeline;
+ _metricsNamespace = metricsNamespace;
}
/// Initializes a new instance of Metrics.
/// Service endpoint.
- /// is null.
- public Metrics(Uri endpoint) : this(endpoint, new SampleTypeSpecClientOptions())
+ ///
+ /// or is null.
+ /// is an empty string, and was expected to be non-empty.
+ public Metrics(Uri endpoint, string metricsNamespace) : this(endpoint, metricsNamespace, new SampleTypeSpecClientOptions())
{
}
/// Initializes a new instance of Metrics.
/// Service endpoint.
+ ///
/// The options for configuring the client.
- /// is null.
- public Metrics(Uri endpoint, SampleTypeSpecClientOptions options)
+ /// or is null.
+ /// is an empty string, and was expected to be non-empty.
+ public Metrics(Uri endpoint, string metricsNamespace, SampleTypeSpecClientOptions options)
{
Argument.AssertNotNull(endpoint, nameof(endpoint));
+ Argument.AssertNotNullOrEmpty(metricsNamespace, nameof(metricsNamespace));
options ??= new SampleTypeSpecClientOptions();
_endpoint = endpoint;
+ _metricsNamespace = metricsNamespace;
Pipeline = ClientPipeline.Create(options, Array.Empty(), new PipelinePolicy[] { new UserAgentPolicy(typeof(Metrics).Assembly) }, Array.Empty());
}
diff --git a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/SampleTypeSpecClient.cs b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/SampleTypeSpecClient.cs
index 016ab1d0d2e..291d40887ea 100644
--- a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/SampleTypeSpecClient.cs
+++ b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/SampleTypeSpecClient.cs
@@ -32,6 +32,7 @@ public partial class SampleTypeSpecClient
}
};
private readonly string _apiVersion;
+ private readonly string _metricsNamespace;
private AnimalOperations _cachedAnimalOperations;
private PetOperations _cachedPetOperations;
private DogOperations _cachedDogOperations;
@@ -45,33 +46,41 @@ protected SampleTypeSpecClient()
/// Initializes a new instance of SampleTypeSpecClient.
/// Service endpoint.
+ ///
/// A credential used to authenticate to the service.
- /// or is null.
- public SampleTypeSpecClient(Uri endpoint, ApiKeyCredential credential) : this(endpoint, credential, new SampleTypeSpecClientOptions())
+ /// , or is null.
+ /// is an empty string, and was expected to be non-empty.
+ public SampleTypeSpecClient(Uri endpoint, string metricsNamespace, ApiKeyCredential credential) : this(endpoint, metricsNamespace, credential, new SampleTypeSpecClientOptions())
{
}
/// Initializes a new instance of SampleTypeSpecClient.
/// Service endpoint.
+ ///
/// A credential provider used to authenticate to the service.
- /// or is null.
- public SampleTypeSpecClient(Uri endpoint, AuthenticationTokenProvider tokenProvider) : this(endpoint, tokenProvider, new SampleTypeSpecClientOptions())
+ /// , or is null.
+ /// is an empty string, and was expected to be non-empty.
+ public SampleTypeSpecClient(Uri endpoint, string metricsNamespace, AuthenticationTokenProvider tokenProvider) : this(endpoint, metricsNamespace, tokenProvider, new SampleTypeSpecClientOptions())
{
}
/// Initializes a new instance of SampleTypeSpecClient.
/// Service endpoint.
+ ///
/// A credential used to authenticate to the service.
/// The options for configuring the client.
- /// or is null.
- public SampleTypeSpecClient(Uri endpoint, ApiKeyCredential credential, SampleTypeSpecClientOptions options)
+ /// , or is null.
+ /// is an empty string, and was expected to be non-empty.
+ public SampleTypeSpecClient(Uri endpoint, string metricsNamespace, ApiKeyCredential credential, SampleTypeSpecClientOptions options)
{
Argument.AssertNotNull(endpoint, nameof(endpoint));
+ Argument.AssertNotNullOrEmpty(metricsNamespace, nameof(metricsNamespace));
Argument.AssertNotNull(credential, nameof(credential));
options ??= new SampleTypeSpecClientOptions();
_endpoint = endpoint;
+ _metricsNamespace = metricsNamespace;
_keyCredential = credential;
Pipeline = ClientPipeline.Create(options, Array.Empty(), new PipelinePolicy[] { new UserAgentPolicy(typeof(SampleTypeSpecClient).Assembly), ApiKeyAuthenticationPolicy.CreateHeaderApiKeyPolicy(_keyCredential, AuthorizationHeader) }, Array.Empty());
_apiVersion = options.Version;
@@ -79,17 +88,21 @@ public SampleTypeSpecClient(Uri endpoint, ApiKeyCredential credential, SampleTyp
/// Initializes a new instance of SampleTypeSpecClient.
/// Service endpoint.
+ ///
/// A credential provider used to authenticate to the service.
/// The options for configuring the client.
- /// or is null.
- public SampleTypeSpecClient(Uri endpoint, AuthenticationTokenProvider tokenProvider, SampleTypeSpecClientOptions options)
+ /// , or is null.
+ /// is an empty string, and was expected to be non-empty.
+ public SampleTypeSpecClient(Uri endpoint, string metricsNamespace, AuthenticationTokenProvider tokenProvider, SampleTypeSpecClientOptions options)
{
Argument.AssertNotNull(endpoint, nameof(endpoint));
+ Argument.AssertNotNullOrEmpty(metricsNamespace, nameof(metricsNamespace));
Argument.AssertNotNull(tokenProvider, nameof(tokenProvider));
options ??= new SampleTypeSpecClientOptions();
_endpoint = endpoint;
+ _metricsNamespace = metricsNamespace;
_tokenProvider = tokenProvider;
Pipeline = ClientPipeline.Create(options, Array.Empty(), new PipelinePolicy[] { new UserAgentPolicy(typeof(SampleTypeSpecClient).Assembly), new BearerTokenPolicy(_tokenProvider, _flows) }, Array.Empty());
_apiVersion = options.Version;
@@ -3317,7 +3330,7 @@ public virtual PlantOperations GetPlantOperationsClient()
/// Initializes a new instance of Metrics.
public virtual Metrics GetMetricsClient()
{
- return Volatile.Read(ref _cachedMetrics) ?? Interlocked.CompareExchange(ref _cachedMetrics, new Metrics(Pipeline, _endpoint), null) ?? _cachedMetrics;
+ return Volatile.Read(ref _cachedMetrics) ?? Interlocked.CompareExchange(ref _cachedMetrics, new Metrics(Pipeline, _endpoint, _metricsNamespace), null) ?? _cachedMetrics;
}
}
}
diff --git a/docs/samples/client/csharp/SampleService/main.tsp b/docs/samples/client/csharp/SampleService/main.tsp
index 2722adc9c6f..d63bf43a53a 100644
--- a/docs/samples/client/csharp/SampleService/main.tsp
+++ b/docs/samples/client/csharp/SampleService/main.tsp
@@ -833,14 +833,19 @@ interface PlantOperations {
};
}
+model MetricsClientParams {
+ metricsNamespace: string;
+}
+
@clientInitialization({
initializedBy: InitializedBy.individually | InitializedBy.parent,
+ parameters: MetricsClientParams,
})
interface Metrics {
@doc("Get Widget metrics for given day of week")
@get
- @route("/metrics/widgets/daysOfWeek")
- getWidgetMetrics(@path day: DaysOfWeekExtensibleEnum): {
+ @route("/metrics/{metricsNamespace}/widgets/daysOfWeek")
+ getWidgetMetrics(@path metricsNamespace: string, @path day: DaysOfWeekExtensibleEnum): {
numSold: int32;
averagePrice: float32;
};
diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs
index 606a888af4c..c58ae32a555 100644
--- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs
+++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ClientProvider.cs
@@ -309,6 +309,22 @@ private IReadOnlyList GetSubClientInternalConstructorParamete
return subClientParameters;
}
+ ///
+ /// Determines whether this subclient has non-infrastructure parameters
+ /// (not API versions, not endpoint) that are not present on the parent's InputClient.Parameters.
+ /// Uses the raw to avoid circular lazy-initialization dependencies.
+ ///
+ internal bool HasAccessorOnlyParameters(InputClient parentInputClient)
+ {
+ var parentParamNames = parentInputClient.Parameters
+ .Select(p => p.Name)
+ .ToHashSet(StringComparer.OrdinalIgnoreCase);
+
+ return _inputClient.Parameters
+ .Where(p => !p.IsApiVersion && !(p is InputEndpointParameter ep && ep.IsEndpoint))
+ .Any(p => !parentParamNames.Contains(p.Name));
+ }
+
private Lazy> _clientParameters;
internal IReadOnlyList ClientParameters => _clientParameters.Value;
private IReadOnlyList GetClientParameters()
@@ -397,7 +413,10 @@ protected override FieldProvider[] BuildFields()
// add sub-client caching fields
foreach (var subClient in _subClients.Value)
{
- if (subClient._clientCachingField != null)
+ // Only add caching field when the accessor does not require additional parameters.
+ // If the subclient has parameters that are not on the parent, each accessor call may
+ // produce a different client instance, so caching is not appropriate.
+ if (subClient._clientCachingField != null && !subClient.HasAccessorOnlyParameters(_inputClient))
{
fields.Add(subClient._clientCachingField);
}
@@ -899,8 +918,19 @@ protected override ScmMethodProvider[] BuildMethods()
var cachedClientFieldVar = new VariableExpression(subClient.Type, subClient._clientCachingField.Declaration, IsRef: true);
List subClientConstructorArgs = new(3);
-
- // Populate constructor arguments
+ List accessorMethodParams = [];
+
+ // Identify subclient-specific parameters by comparing with the parent's input parameters.
+ // Parameters present on both parent and subclient are shared (sourced from parent fields/properties).
+ var parentInputParamNames = _inputClient.Parameters
+ .Select(p => p.Name)
+ .ToHashSet(StringComparer.OrdinalIgnoreCase);
+ var subClientSpecificParamNames = subClient._inputClient.Parameters
+ .Where(p => !parentInputParamNames.Contains(p.Name))
+ .Select(p => p.Name)
+ .ToHashSet(StringComparer.OrdinalIgnoreCase);
+
+ // Populate constructor arguments, collecting subclient-specific params for the accessor method signature
foreach (var param in subClient._subClientInternalConstructorParams.Value)
{
if (parentClientProperties.TryGetValue(param.Name, out var parentProperty))
@@ -920,30 +950,57 @@ protected override ScmMethodProvider[] BuildMethods()
subClientConstructorArgs.Add(correspondingApiVersionField.Field);
}
}
+ else if (subClientSpecificParamNames.Contains(param.Name))
+ {
+ // This parameter is subclient-specific — expose it as an accessor method parameter.
+ accessorMethodParams.Add(param);
+ subClientConstructorArgs.Add(param);
+ }
}
- // Create the interlocked compare exchange expression for the body
- var interlockedCompareExchange = Static(typeof(Interlocked)).Invoke(
- nameof(Interlocked.CompareExchange),
- [cachedClientFieldVar, New.Instance(subClient.Type, subClientConstructorArgs), Null]);
var factoryMethodName = subClient.Name.EndsWith(ClientSuffix, StringComparison.OrdinalIgnoreCase)
? $"Get{subClient.Name}"
: $"Get{subClient.Name}{ClientSuffix}";
- var factoryMethod = new ScmMethodProvider(
- new(
- factoryMethodName,
- $"Initializes a new instance of {subClient.Type.Name}",
- MethodSignatureModifiers.Public | MethodSignatureModifiers.Virtual,
- subClient.Type,
- null,
- []),
- // return Volatile.Read(ref _cachedClient) ?? Interlocked.CompareExchange(ref _cachedClient, new Client(_pipeline, _keyCredential, _endpoint), null) ?? _cachedClient;
- Return(
- Static(typeof(Volatile)).Invoke(nameof(Volatile.Read), cachedClientFieldVar)
- .NullCoalesce(interlockedCompareExchange.NullCoalesce(subClient._clientCachingField))),
- this,
- ScmMethodKind.Convenience);
+ ScmMethodProvider factoryMethod;
+ if (accessorMethodParams.Count > 0)
+ {
+ // When the accessor requires extra parameters, caching is not appropriate
+ // (different parameter values may produce different client instances).
+ // Return a new instance directly.
+ factoryMethod = new ScmMethodProvider(
+ new(
+ factoryMethodName,
+ $"Initializes a new instance of {subClient.Type.Name}",
+ MethodSignatureModifiers.Public | MethodSignatureModifiers.Virtual,
+ subClient.Type,
+ null,
+ [.. accessorMethodParams]),
+ Return(New.Instance(subClient.Type, subClientConstructorArgs)),
+ this,
+ ScmMethodKind.Convenience);
+ }
+ else
+ {
+ // No extra params - use the existing caching pattern
+ var interlockedCompareExchange = Static(typeof(Interlocked)).Invoke(
+ nameof(Interlocked.CompareExchange),
+ [cachedClientFieldVar, New.Instance(subClient.Type, subClientConstructorArgs), Null]);
+ factoryMethod = new ScmMethodProvider(
+ new(
+ factoryMethodName,
+ $"Initializes a new instance of {subClient.Type.Name}",
+ MethodSignatureModifiers.Public | MethodSignatureModifiers.Virtual,
+ subClient.Type,
+ null,
+ []),
+ // return Volatile.Read(ref _cachedClient) ?? Interlocked.CompareExchange(ref _cachedClient, new Client(_pipeline, _keyCredential, _endpoint), null) ?? _cachedClient;
+ Return(
+ Static(typeof(Volatile)).Invoke(nameof(Volatile.Read), cachedClientFieldVar)
+ .NullCoalesce(interlockedCompareExchange.NullCoalesce(subClient._clientCachingField))),
+ this,
+ ScmMethodKind.Convenience);
+ }
methods.Add(factoryMethod);
}
diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs
index 9d1a8bbacdf..48554a37f83 100644
--- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs
+++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs
@@ -899,6 +899,116 @@ public void TestBuildMethods_ForParent_InitializedByBoth_HasSubClientAccessor()
Assert.IsNotNull(cachingField, "Parent should have caching field for subclient with InitializedBy.Individually | Parent");
}
+ [Test]
+ public void TestBuildMethods_ForParent_InitializedByBoth_WithSubClientParams_HasParameterizedAccessor()
+ {
+ var parentClient = InputFactory.Client("ParentClient");
+ var subClientParam = InputFactory.PathParameter("resourceId", InputPrimitiveType.String, scope: InputParameterScope.Client);
+ var subClient = InputFactory.Client(
+ "SubClient",
+ parent: parentClient,
+ parameters: [subClientParam],
+ initializedBy: InputClientInitializedBy.Individually | InputClientInitializedBy.Parent);
+
+ MockHelpers.LoadMockGenerator(
+ clients: () => [parentClient]);
+
+ var parentProvider = new ClientProvider(parentClient);
+
+ Assert.IsNotNull(parentProvider);
+
+ // The parent should have a factory method for the subclient
+ var factoryMethod = parentProvider.Methods.FirstOrDefault(
+ m => m.Signature?.Name == "GetSubClient" || m.Signature?.Name == "GetSubClientClient");
+ Assert.IsNotNull(factoryMethod, "Parent should have factory method for subclient with parameters");
+
+ // The accessor method should include the subclient's extra parameters
+ Assert.IsNotNull(factoryMethod!.Signature, "Factory method should have a signature");
+ Assert.AreEqual(1, factoryMethod.Signature!.Parameters.Count,
+ "Accessor method should include subclient parameters not present on parent");
+ Assert.AreEqual("resourceId", factoryMethod.Signature.Parameters[0].Name,
+ "Accessor method parameter should be the subclient's extra parameter");
+ }
+
+ [Test]
+ public void TestBuildFields_ForParent_InitializedByBoth_WithSubClientParams_NoCachingField()
+ {
+ var parentClient = InputFactory.Client("ParentClient");
+ var subClientParam = InputFactory.PathParameter("resourceId", InputPrimitiveType.String, scope: InputParameterScope.Client);
+ var subClient = InputFactory.Client(
+ "SubClient",
+ parent: parentClient,
+ parameters: [subClientParam],
+ initializedBy: InputClientInitializedBy.Individually | InputClientInitializedBy.Parent);
+
+ MockHelpers.LoadMockGenerator(
+ clients: () => [parentClient]);
+
+ var parentProvider = new ClientProvider(parentClient);
+
+ Assert.IsNotNull(parentProvider);
+
+ // The parent should NOT have a caching field for the subclient when the accessor requires parameters,
+ // since caching is not appropriate when different parameter values produce different client instances.
+ var cachingField = parentProvider.Fields.FirstOrDefault(f => f.Name == "_cachedSubClient");
+ Assert.IsNull(cachingField, "Parent should not have caching field for subclient that has subclient-specific parameters in its accessor");
+ }
+
+ [Test]
+ public void TestBuildMethods_ForParent_InitializedByParentOnly_WithSubClientParams_HasParameterizedAccessor()
+ {
+ var parentClient = InputFactory.Client("ParentClient");
+ var subClientParam = InputFactory.PathParameter("resourceId", InputPrimitiveType.String, scope: InputParameterScope.Client);
+ var subClient = InputFactory.Client(
+ "SubClient",
+ parent: parentClient,
+ parameters: [subClientParam],
+ initializedBy: InputClientInitializedBy.Parent);
+
+ MockHelpers.LoadMockGenerator(
+ clients: () => [parentClient]);
+
+ var parentProvider = new ClientProvider(parentClient);
+
+ Assert.IsNotNull(parentProvider);
+
+ // The parent should have a factory method for the subclient
+ var factoryMethod = parentProvider.Methods.FirstOrDefault(
+ m => m.Signature?.Name == "GetSubClient" || m.Signature?.Name == "GetSubClientClient");
+ Assert.IsNotNull(factoryMethod, "Parent should have factory method for subclient with parameters");
+
+ // The accessor method should include the subclient's extra parameters
+ Assert.IsNotNull(factoryMethod!.Signature, "Factory method should have a signature");
+ Assert.AreEqual(1, factoryMethod.Signature!.Parameters.Count,
+ "Accessor method should include subclient parameters not present on parent");
+ Assert.AreEqual("resourceId", factoryMethod.Signature.Parameters[0].Name,
+ "Accessor method parameter should be the subclient's extra parameter");
+ }
+
+ [Test]
+ public void TestBuildFields_ForParent_InitializedByParentOnly_WithSubClientParams_NoCachingField()
+ {
+ var parentClient = InputFactory.Client("ParentClient");
+ var subClientParam = InputFactory.PathParameter("resourceId", InputPrimitiveType.String, scope: InputParameterScope.Client);
+ var subClient = InputFactory.Client(
+ "SubClient",
+ parent: parentClient,
+ parameters: [subClientParam],
+ initializedBy: InputClientInitializedBy.Parent);
+
+ MockHelpers.LoadMockGenerator(
+ clients: () => [parentClient]);
+
+ var parentProvider = new ClientProvider(parentClient);
+
+ Assert.IsNotNull(parentProvider);
+
+ // The parent should NOT have a caching field for the subclient when the accessor requires parameters,
+ // since caching is not appropriate when different parameter values produce different client instances.
+ var cachingField = parentProvider.Fields.FirstOrDefault(f => f.Name == "_cachedSubClient");
+ Assert.IsNull(cachingField, "Parent should not have caching field for subclient that has subclient-specific parameters in its accessor");
+ }
+
private void ValidatePrimaryConstructor(
ConstructorProvider primaryPublicConstructor,
List inputParameters,
diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Metrics.RestClient.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Metrics.RestClient.cs
index a724f1907ef..697b9766d36 100644
--- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Metrics.RestClient.cs
+++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Metrics.RestClient.cs
@@ -20,7 +20,9 @@ internal PipelineMessage CreateGetWidgetMetricsRequest(string day, RequestOption
{
ClientUriBuilder uri = new ClientUriBuilder();
uri.Reset(_endpoint);
- uri.AppendPath("/metrics/widgets/daysOfWeek/", false);
+ uri.AppendPath("/metrics/", false);
+ uri.AppendPath(_metricsNamespace, true);
+ uri.AppendPath("/widgets/daysOfWeek/", false);
uri.AppendPath(day, true);
PipelineMessage message = Pipeline.CreateMessage(uri.ToUri(), "GET", PipelineMessageClassifier200);
PipelineRequest request = message.Request;
diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Metrics.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Metrics.cs
index 8f9c0ffffb6..8e55488af08 100644
--- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Metrics.cs
+++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Metrics.cs
@@ -17,6 +17,7 @@ namespace SampleTypeSpec
public partial class Metrics
{
private readonly Uri _endpoint;
+ private readonly string _metricsNamespace;
/// Initializes a new instance of Metrics for mocking.
protected Metrics()
@@ -26,30 +27,38 @@ protected Metrics()
/// Initializes a new instance of Metrics.
/// The HTTP pipeline for sending and receiving REST requests and responses.
/// Service endpoint.
- internal Metrics(ClientPipeline pipeline, Uri endpoint)
+ ///
+ internal Metrics(ClientPipeline pipeline, Uri endpoint, string metricsNamespace)
{
_endpoint = endpoint;
Pipeline = pipeline;
+ _metricsNamespace = metricsNamespace;
}
/// Initializes a new instance of Metrics.
/// Service endpoint.
- /// is null.
- public Metrics(Uri endpoint) : this(endpoint, new SampleTypeSpecClientOptions())
+ ///
+ /// or is null.
+ /// is an empty string, and was expected to be non-empty.
+ public Metrics(Uri endpoint, string metricsNamespace) : this(endpoint, metricsNamespace, new SampleTypeSpecClientOptions())
{
}
/// Initializes a new instance of Metrics.
/// Service endpoint.
+ ///
/// The options for configuring the client.
- /// is null.
- public Metrics(Uri endpoint, SampleTypeSpecClientOptions options)
+ /// or is null.
+ /// is an empty string, and was expected to be non-empty.
+ public Metrics(Uri endpoint, string metricsNamespace, SampleTypeSpecClientOptions options)
{
Argument.AssertNotNull(endpoint, nameof(endpoint));
+ Argument.AssertNotNullOrEmpty(metricsNamespace, nameof(metricsNamespace));
options ??= new SampleTypeSpecClientOptions();
_endpoint = endpoint;
+ _metricsNamespace = metricsNamespace;
Pipeline = ClientPipeline.Create(options, Array.Empty(), new PipelinePolicy[] { new UserAgentPolicy(typeof(Metrics).Assembly) }, Array.Empty());
}
diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.cs
index f2e56c36cb0..cc40aaedfa9 100644
--- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.cs
+++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/SampleTypeSpecClient.cs
@@ -40,7 +40,6 @@ public partial class SampleTypeSpecClient
private PetOperations _cachedPetOperations;
private DogOperations _cachedDogOperations;
private PlantOperations _cachedPlantOperations;
- private Metrics _cachedMetrics;
/// Initializes a new instance of SampleTypeSpecClient for mocking.
protected SampleTypeSpecClient()
@@ -1907,9 +1906,13 @@ public virtual PlantOperations GetPlantOperationsClient()
}
/// Initializes a new instance of Metrics.
- public virtual Metrics GetMetricsClient()
+ ///
+ /// is null.
+ public virtual Metrics GetMetricsClient(string metricsNamespace)
{
- return Volatile.Read(ref _cachedMetrics) ?? Interlocked.CompareExchange(ref _cachedMetrics, new Metrics(Pipeline, _endpoint), null) ?? _cachedMetrics;
+ Argument.AssertNotNull(metricsNamespace, nameof(metricsNamespace));
+
+ return new Metrics(Pipeline, _endpoint, metricsNamespace);
}
}
}
diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/tspCodeModel.json b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/tspCodeModel.json
index 2fd876c5106..459ab161e6f 100644
--- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/tspCodeModel.json
+++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/tspCodeModel.json
@@ -13044,6 +13044,52 @@
{
"$id": "866",
"kind": "path",
+ "name": "metricsNamespace",
+ "serializedName": "metricsNamespace",
+ "type": {
+ "$id": "867",
+ "kind": "string",
+ "name": "string",
+ "crossLanguageDefinitionId": "TypeSpec.string",
+ "decorators": []
+ },
+ "isApiVersion": false,
+ "explode": false,
+ "style": "simple",
+ "allowReserved": false,
+ "skipUrlEncoding": false,
+ "optional": false,
+ "scope": "Client",
+ "decorators": [],
+ "readOnly": false,
+ "crossLanguageDefinitionId": "SampleTypeSpec.Metrics.getWidgetMetrics.metricsNamespace",
+ "methodParameterSegments": [
+ {
+ "$id": "868",
+ "kind": "method",
+ "name": "metricsNamespace",
+ "serializedName": "metricsNamespace",
+ "type": {
+ "$id": "869",
+ "kind": "string",
+ "name": "string",
+ "crossLanguageDefinitionId": "TypeSpec.string",
+ "decorators": []
+ },
+ "location": "",
+ "isApiVersion": false,
+ "optional": false,
+ "scope": "Method",
+ "crossLanguageDefinitionId": "SampleTypeSpec.MetricsClientParams.metricsNamespace",
+ "readOnly": false,
+ "access": "public",
+ "decorators": []
+ }
+ ]
+ },
+ {
+ "$id": "870",
+ "kind": "path",
"name": "day",
"serializedName": "day",
"type": {
@@ -13061,7 +13107,7 @@
"crossLanguageDefinitionId": "SampleTypeSpec.Metrics.getWidgetMetrics.day",
"methodParameterSegments": [
{
- "$id": "867",
+ "$id": "871",
"kind": "method",
"name": "day",
"serializedName": "day",
@@ -13080,7 +13126,7 @@
]
},
{
- "$id": "868",
+ "$id": "872",
"kind": "header",
"name": "accept",
"serializedName": "Accept",
@@ -13096,7 +13142,7 @@
"crossLanguageDefinitionId": "SampleTypeSpec.Metrics.getWidgetMetrics.accept",
"methodParameterSegments": [
{
- "$id": "869",
+ "$id": "873",
"kind": "method",
"name": "accept",
"serializedName": "Accept",
@@ -13132,7 +13178,7 @@
],
"httpMethod": "GET",
"uri": "{sampleTypeSpecUrl}",
- "path": "/metrics/widgets/daysOfWeek/{day}",
+ "path": "/metrics/{metricsNamespace}/widgets/daysOfWeek/{day}",
"bufferResponse": true,
"generateProtocolMethod": true,
"generateConvenienceMethod": true,
@@ -13142,10 +13188,10 @@
},
"parameters": [
{
- "$ref": "867"
+ "$ref": "871"
},
{
- "$ref": "869"
+ "$ref": "873"
}
],
"response": {
@@ -13161,12 +13207,12 @@
],
"parameters": [
{
- "$id": "870",
+ "$id": "874",
"kind": "endpoint",
"name": "sampleTypeSpecUrl",
"serializedName": "sampleTypeSpecUrl",
"type": {
- "$id": "871",
+ "$id": "875",
"kind": "url",
"name": "endpoint",
"crossLanguageDefinitionId": "TypeSpec.url"
@@ -13179,6 +13225,9 @@
"skipUrlEncoding": false,
"readOnly": false,
"crossLanguageDefinitionId": "SampleTypeSpec.Metrics.sampleTypeSpecUrl"
+ },
+ {
+ "$ref": "868"
}
],
"initializedBy": 3,