Skip to content

Commit ad0be8c

Browse files
authored
Add public constructor for metadata (Azure#52325)
* Add public constructr for metadata * Fix * Revert "Fix" This reverts commit efe9f63. * Fix * Fixes * Fix II * Fix III
1 parent a9d0bb6 commit ad0be8c

File tree

6 files changed

+189
-32
lines changed

6 files changed

+189
-32
lines changed

sdk/core/System.ClientModel/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Features Added
66

7+
- Added `ClientConnection` constructor, accepting credentials and metadata.
8+
79
### Breaking Changes
810

911
### Bugs Fixed

sdk/core/System.ClientModel/api/System.ClientModel.net8.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ public readonly partial struct ClientConnection
125125
private readonly int _dummyPrimitive;
126126
public ClientConnection(string id, string locator) { throw null; }
127127
public ClientConnection(string id, string locator, object credential, System.ClientModel.Primitives.CredentialKind credentialKind) { throw null; }
128+
public ClientConnection(string id, string locator, object? credential, System.ClientModel.Primitives.CredentialKind credentialKind, System.Collections.Generic.IReadOnlyDictionary<string, string>? metadata) { throw null; }
128129
public object? Credential { get { throw null; } }
129130
public System.ClientModel.Primitives.CredentialKind CredentialKind { get { throw null; } }
130131
public string Id { get { throw null; } }

sdk/core/System.ClientModel/api/System.ClientModel.netstandard2.0.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ public readonly partial struct ClientConnection
124124
private readonly int _dummyPrimitive;
125125
public ClientConnection(string id, string locator) { throw null; }
126126
public ClientConnection(string id, string locator, object credential, System.ClientModel.Primitives.CredentialKind credentialKind) { throw null; }
127+
public ClientConnection(string id, string locator, object? credential, System.ClientModel.Primitives.CredentialKind credentialKind, System.Collections.Generic.IReadOnlyDictionary<string, string>? metadata) { throw null; }
127128
public object? Credential { get { throw null; } }
128129
public System.ClientModel.Primitives.CredentialKind CredentialKind { get { throw null; } }
129130
public string Id { get { throw null; } }

sdk/core/System.ClientModel/src/Convenience/ClientConnection.cs

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
3-
using System.Collections.ObjectModel;
43

54
namespace System.ClientModel.Primitives;
65

@@ -16,39 +15,16 @@ public readonly struct ClientConnection
1615
/// <param name="locator">The endpoint or resource identifier.</param>
1716
/// <param name="credential">The client credential.</param>
1817
/// <param name="credentialKind">The kind of connection used by the client.</param>
19-
public ClientConnection(string id, string locator, object credential, CredentialKind credentialKind)
20-
{
21-
if (string.IsNullOrWhiteSpace(id))
22-
throw new ArgumentException("Id cannot be null or empty.", nameof(id));
23-
if (string.IsNullOrWhiteSpace(locator))
24-
throw new ArgumentException("Locator cannot be null or empty.", nameof(locator));
25-
if (credential is null)
26-
throw new ArgumentNullException(nameof(credential), "Credential cannot be null.");
27-
28-
Id = id;
29-
Locator = locator;
30-
Credential = credential;
31-
CredentialKind = credentialKind;
32-
Metadata = new Dictionary<string, string>();
33-
}
18+
public ClientConnection(string id, string locator, object credential, CredentialKind credentialKind): this(id: id, locator: locator, credentialKind: credentialKind, credential: credential, metadata: null)
19+
{}
3420

3521
/// <summary>
3622
/// Initializes a new instance of the <see cref="ClientConnection"/> struct with a with no authentication.
3723
/// </summary>
3824
/// <param name="id">The identifier for the connection.</param>
3925
/// <param name="locator">The endpoint or resource identifier.</param>
40-
public ClientConnection(string id, string locator)
41-
{
42-
if (string.IsNullOrWhiteSpace(id))
43-
throw new ArgumentException("Id cannot be null or empty.", nameof(id));
44-
if (string.IsNullOrWhiteSpace(locator))
45-
throw new ArgumentException("Locator cannot be null or empty.", nameof(locator));
46-
47-
Id = id;
48-
Locator = locator;
49-
CredentialKind = CredentialKind.None;
50-
Metadata = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>());
51-
}
26+
public ClientConnection(string id, string locator) : this(id: id, locator: locator, credentialKind: CredentialKind.None, credential: null, metadata: null)
27+
{}
5228

5329
/// <summary>
5430
/// Initializes a new instance of the <see cref="ClientConnection"/> struct with the specified subclient ID.
@@ -62,23 +38,42 @@ internal ClientConnection(string id, string locator, CredentialKind credentialKi
6238
Id = id;
6339
Locator = locator;
6440
CredentialKind = credentialKind;
65-
Metadata = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>());
41+
Metadata = new Dictionary<string, string>();
6642
}
6743

6844
/// <summary>
6945
/// Initializes a new instance of the <see cref="ClientConnection"/> struct with the specified subclient ID.
7046
/// It is only for the JSON serializer.
7147
/// </summary>
72-
/// <param name="metadata">The connection metadata.</param>
7348
/// <param name="id">The identifier for the connection.</param>
7449
/// <param name="locator">The endpoint or resource identifier.</param>
50+
/// <param name="credential">The client credential.</param>
7551
/// <param name="credentialKind">The kind of connection used by the client</param>
76-
internal ClientConnection(IReadOnlyDictionary<string, string> metadata, string id, string locator, CredentialKind credentialKind)
52+
/// <param name="metadata">The connection metadata.</param>
53+
public ClientConnection(string id, string locator, object? credential, CredentialKind credentialKind, IReadOnlyDictionary<string, string>? metadata)
7754
{
55+
if (string.IsNullOrWhiteSpace(id))
56+
{
57+
throw new ArgumentException("Id cannot be null or empty.", nameof(id));
58+
}
59+
if (string.IsNullOrWhiteSpace(locator))
60+
{
61+
throw new ArgumentException("Locator cannot be null or empty.", nameof(locator));
62+
}
63+
if (credential is null && credentialKind != CredentialKind.None)
64+
{
65+
throw new ArgumentNullException(nameof(credential), "Credential cannot be null.");
66+
}
67+
if (metadata is null)
68+
{
69+
Metadata = new Dictionary<string, string>();
70+
}
71+
else
72+
Metadata = metadata;
7873
Id = id;
7974
Locator = locator;
75+
Credential = credential;
8076
CredentialKind = credentialKind;
81-
Metadata = metadata;
8277
}
8378

8479
/// <summary>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.14.36301.6
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.ClientModel", "System.ClientModel.csproj", "{C47123BB-B46C-6DFD-67C5-5FA5177F83DD}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.ClientModel.Tests", "..\tests\System.ClientModel.Tests.csproj", "{F6F4AC2B-5001-10AC-4C5D-2E198C56DA64}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{C47123BB-B46C-6DFD-67C5-5FA5177F83DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{C47123BB-B46C-6DFD-67C5-5FA5177F83DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{C47123BB-B46C-6DFD-67C5-5FA5177F83DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{C47123BB-B46C-6DFD-67C5-5FA5177F83DD}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{F6F4AC2B-5001-10AC-4C5D-2E198C56DA64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{F6F4AC2B-5001-10AC-4C5D-2E198C56DA64}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{F6F4AC2B-5001-10AC-4C5D-2E198C56DA64}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{F6F4AC2B-5001-10AC-4C5D-2E198C56DA64}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {E1C04059-C321-4396-9D01-A02FC6ED3577}
30+
EndGlobalSection
31+
EndGlobal
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
using System.Collections.Generic;
4+
using NUnit.Framework;
5+
6+
namespace System.ClientModel.Primitives.Tests;
7+
8+
public class ClientConnectionTests
9+
{
10+
[Test]
11+
[TestCase(null, false)]
12+
[TestCase(CredentialKind.TokenCredential, false)]
13+
[TestCase(CredentialKind.TokenCredential, true)]
14+
public void TestClientConnectionConstructor(CredentialKind? credentialKind, bool hasMetadata)
15+
{
16+
ClientConnection conn;
17+
if (credentialKind is null)
18+
{
19+
conn = new(id: "123", locator: "www.microsoft.com");
20+
Assert.IsNull(conn.Credential);
21+
Assert.AreEqual(CredentialKind.None, conn.CredentialKind);
22+
Assert.AreEqual(0, conn.Metadata.Count);
23+
}
24+
else
25+
{
26+
object credential = new { foo = "bar" };
27+
if (!hasMetadata)
28+
{
29+
conn = new(id: "123", locator: "www.microsoft.com", credential: credential, credentialKind: credentialKind.Value);
30+
Assert.AreEqual(conn.Metadata.Count, 0);
31+
}
32+
else
33+
{
34+
var metadata = new Dictionary<string, string>
35+
{
36+
{ "test1", "123"},
37+
{ "test2", "456" }
38+
};
39+
conn = new(id: "123", locator: "www.microsoft.com", credential: credential, credentialKind: credentialKind.Value, metadata: metadata);
40+
Assert.AreEqual(conn.Metadata.Count, metadata.Count);
41+
}
42+
Assert.AreEqual(conn.CredentialKind, credentialKind);
43+
Assert.AreEqual(conn.Credential, credential);
44+
}
45+
Assert.AreEqual(conn.Id, "123");
46+
Assert.AreEqual(conn.Locator, "www.microsoft.com");
47+
}
48+
49+
#nullable disable
50+
[Test]
51+
[TestCase(null, "Id cannot be null or empty.")]
52+
[TestCase("123", "Locator cannot be null or empty.")]
53+
public void TestConstructorThrows(string id, string expected)
54+
{
55+
ArgumentException exception = Assert.Throws<ArgumentException>(() => new ClientConnection(id: id, locator: null));
56+
Assert.That(exception.Message.StartsWith(expected));
57+
}
58+
59+
[Test]
60+
[TestCase(null, null, "Id cannot be null or empty.")]
61+
[TestCase("123", null, "Locator cannot be null or empty.")]
62+
[TestCase("", "", "Id cannot be null or empty.")]
63+
[TestCase("123", "", "Locator cannot be null or empty.")]
64+
public void TestConstructorWithCredentialsThrows(string id, string locator, string expected)
65+
{
66+
ArgumentException exception = Assert.Throws<ArgumentException>(() => new ClientConnection(id: id, locator: locator, credentialKind: CredentialKind.TokenCredential, credential: null));
67+
Assert.That(exception.Message.StartsWith(expected));
68+
}
69+
70+
[Test]
71+
public void TestConstructorWithCredentialsThrowsArgumentNull()
72+
{
73+
ArgumentException exception = Assert.Throws<ArgumentNullException>(
74+
() => new ClientConnection(id: "123", locator: "www.microsoft.com", credentialKind: CredentialKind.TokenCredential, credential: null));
75+
Assert.That(exception.Message.StartsWith("Credential cannot be null."));
76+
}
77+
78+
[Test]
79+
public void TestConstructorWithCredentialsNone()
80+
{
81+
ClientConnection conn = new(id: "123", locator: "www.microsoft.com", credential: null, credentialKind: CredentialKind.None);
82+
Assert.AreEqual("123", conn.Id);
83+
Assert.AreEqual("www.microsoft.com", conn.Locator);
84+
Assert.AreEqual(CredentialKind.None, conn.CredentialKind);
85+
Assert.AreEqual(0, conn.Metadata.Count);
86+
}
87+
88+
[Test]
89+
[TestCase(null, null, null, "Id cannot be null or empty.")]
90+
[TestCase("123", null, null, "Locator cannot be null or empty.")]
91+
[TestCase("", "", null, "Id cannot be null or empty.")]
92+
[TestCase("123", "", null, "Locator cannot be null or empty.")]
93+
public void TestConstructorWithMetadataThrows(string id, string locator, object credential, string expected)
94+
{
95+
ArgumentException exception = Assert.Throws<ArgumentException>(() => new ClientConnection(id: id, locator: locator, credentialKind: CredentialKind.TokenCredential, credential: credential, metadata: null));
96+
Assert.That(exception.Message.StartsWith(expected), $"Expected: {expected}, got: {exception.Message}");
97+
}
98+
99+
[Test]
100+
public void TestConstructorWithMetadataThrowsArgumentNull()
101+
{
102+
ArgumentException exception = Assert.Throws<ArgumentNullException>(() => new ClientConnection(id: "123", locator: "www.microsoft.com", credentialKind: CredentialKind.TokenCredential, credential: null, metadata: null));
103+
Assert.That(exception.Message.StartsWith("Credential cannot be null."), $"Expected: \"Credential cannot be null.\", got: {exception.Message}");
104+
}
105+
106+
[Test]
107+
[TestCase(0)]
108+
[TestCase(2)]
109+
public void TestConstructorMetadataWithNull(int dictionarySize)
110+
{
111+
Dictionary<string, string> metadata = null;
112+
if (dictionarySize > 0)
113+
{
114+
metadata = [];
115+
for (int i = 0; i < dictionarySize; i++)
116+
{
117+
metadata[$"key{i}"] = $"value{i}";
118+
}
119+
}
120+
ClientConnection conn = new(id: "123", locator: "www.microsoft.com", credential: null, credentialKind: CredentialKind.None, metadata: metadata);
121+
Assert.AreEqual("123", conn.Id);
122+
Assert.AreEqual("www.microsoft.com", conn.Locator);
123+
Assert.AreEqual(CredentialKind.None, conn.CredentialKind);
124+
Assert.AreEqual(dictionarySize, conn.Metadata.Count);
125+
}
126+
#nullable enable
127+
}

0 commit comments

Comments
 (0)