Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClientModel: Add async and sync enumerable client results #43392

Closed
14 changes: 13 additions & 1 deletion sdk/core/System.ClientModel/api/System.ClientModel.net6.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ public ApiKeyCredential(string key) { }
public static implicit operator System.ClientModel.ApiKeyCredential (string key) { throw null; }
public void Update(string key) { }
}
public abstract partial class AsyncClientResultCollection<T> : System.ClientModel.ClientResult, System.Collections.Generic.IAsyncEnumerable<T>
{
protected internal AsyncClientResultCollection(System.ClientModel.Primitives.PipelineResponse response) : base (default(System.ClientModel.Primitives.PipelineResponse)) { }
public abstract System.Collections.Generic.IAsyncEnumerator<T> GetAsyncEnumerator(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
}
public abstract partial class BinaryContent : System.IDisposable
{
protected BinaryContent() { }
Expand All @@ -20,11 +25,18 @@ protected BinaryContent() { }
}
public partial class ClientResult
{
protected ClientResult(System.ClientModel.Primitives.PipelineResponse response) { }
protected ClientResult(System.ClientModel.Primitives.PipelineResponse? response) { }
public static System.ClientModel.ClientResult<T?> FromOptionalValue<T>(T? value, System.ClientModel.Primitives.PipelineResponse response) { throw null; }
public static System.ClientModel.ClientResult FromResponse(System.ClientModel.Primitives.PipelineResponse response) { throw null; }
public static System.ClientModel.ClientResult<T> FromValue<T>(T value, System.ClientModel.Primitives.PipelineResponse response) { throw null; }
public System.ClientModel.Primitives.PipelineResponse GetRawResponse() { throw null; }
protected void SetRawResponse(System.ClientModel.Primitives.PipelineResponse response) { }
}
public abstract partial class ClientResultCollection<T> : System.ClientModel.ClientResult, System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable
{
protected internal ClientResultCollection(System.ClientModel.Primitives.PipelineResponse response) : base (default(System.ClientModel.Primitives.PipelineResponse)) { }
public abstract System.Collections.Generic.IEnumerator<T> GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
}
public partial class ClientResultException : System.Exception
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ public ApiKeyCredential(string key) { }
public static implicit operator System.ClientModel.ApiKeyCredential (string key) { throw null; }
public void Update(string key) { }
}
public abstract partial class AsyncClientResultCollection<T> : System.ClientModel.ClientResult, System.Collections.Generic.IAsyncEnumerable<T>
{
protected internal AsyncClientResultCollection(System.ClientModel.Primitives.PipelineResponse response) : base (default(System.ClientModel.Primitives.PipelineResponse)) { }
public abstract System.Collections.Generic.IAsyncEnumerator<T> GetAsyncEnumerator(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
}
public abstract partial class BinaryContent : System.IDisposable
{
protected BinaryContent() { }
Expand All @@ -20,11 +25,18 @@ protected BinaryContent() { }
}
public partial class ClientResult
{
protected ClientResult(System.ClientModel.Primitives.PipelineResponse response) { }
protected ClientResult(System.ClientModel.Primitives.PipelineResponse? response) { }
public static System.ClientModel.ClientResult<T?> FromOptionalValue<T>(T? value, System.ClientModel.Primitives.PipelineResponse response) { throw null; }
public static System.ClientModel.ClientResult FromResponse(System.ClientModel.Primitives.PipelineResponse response) { throw null; }
public static System.ClientModel.ClientResult<T> FromValue<T>(T value, System.ClientModel.Primitives.PipelineResponse response) { throw null; }
public System.ClientModel.Primitives.PipelineResponse GetRawResponse() { throw null; }
protected void SetRawResponse(System.ClientModel.Primitives.PipelineResponse response) { }
}
public abstract partial class ClientResultCollection<T> : System.ClientModel.ClientResult, System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable
{
protected internal ClientResultCollection(System.ClientModel.Primitives.PipelineResponse response) : base (default(System.ClientModel.Primitives.PipelineResponse)) { }
public abstract System.Collections.Generic.IEnumerator<T> GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
}
public partial class ClientResultException : System.Exception
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Threading;

namespace System.ClientModel;

#pragma warning disable CS1591 // public XML comments
public abstract class AsyncClientResultCollection<T> : ClientResult, IAsyncEnumerable<T>
{
protected internal AsyncClientResultCollection(PipelineResponse response) : base(response)
{
}

public abstract IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default);
}
#pragma warning restore CS1591 // public XML comments
52 changes: 45 additions & 7 deletions sdk/core/System.ClientModel/src/Convenience/ClientResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,16 @@ namespace System.ClientModel;
/// </summary>
public class ClientResult
{
private readonly PipelineResponse _response;
private PipelineResponse? _response;

/// <summary>
/// Create a new instance of <see cref="ClientResult"/> from a service
/// response.
/// </summary>
/// <param name="response">The <see cref="PipelineResponse"/> received
/// from the service.</param>
protected ClientResult(PipelineResponse response)
protected ClientResult(PipelineResponse? response)
{
Argument.AssertNotNull(response, nameof(response));

_response = response;
}

Expand All @@ -31,7 +29,37 @@ protected ClientResult(PipelineResponse response)
/// </summary>
/// <returns>the <see cref="PipelineResponse"/> received from the service.
/// </returns>
public PipelineResponse GetRawResponse() => _response;
/// <exception cref="InvalidOperationException">No
/// <see cref="PipelineResponse"/> value is currently available for this
/// <see cref="ClientResult"/> instance. This can happen when the instance
/// is a collection type like <see cref="AsyncClientResultCollection{T}"/>
/// that has not yet been enumerated.</exception>
public PipelineResponse GetRawResponse()
{
if (_response is null)
{
throw new InvalidOperationException("No response is associated " +
"with this result. If the result is a collection result " +
"type, this may be because no request has been sent to the " +
"server yet.");
}

return _response;
}

/// <summary>
/// Update the value returned from <see cref="GetRawResponse"/>.
/// </summary>
/// <remarks>This method may be called from types derived from
/// <see cref="ClientResult"/> that poll the service for status updates
/// or to retrieve additional collection values to update the raw response
/// to the response most recently returned from the service.</remarks>
/// <param name="response">The <see cref="PipelineResponse"/> to return
/// from <see cref="GetRawResponse"/>.</param>
protected void SetRawResponse(PipelineResponse response)
{
_response = response;
}

#region Factory methods for ClientResult and subtypes

Expand All @@ -44,7 +72,11 @@ protected ClientResult(PipelineResponse response)
/// provided <paramref name="response"/>.
/// </returns>
public static ClientResult FromResponse(PipelineResponse response)
=> new ClientResult(response);
{
Argument.AssertNotNull(response, nameof(response));

return new ClientResult(response);
}

/// <summary>
/// Creates a new instance of <see cref="ClientResult{T}"/> that holds the
Expand All @@ -60,6 +92,8 @@ public static ClientResult FromResponse(PipelineResponse response)
/// </returns>
public static ClientResult<T> FromValue<T>(T value, PipelineResponse response)
{
Argument.AssertNotNull(response, nameof(response));

if (value is null)
{
string message = "ClientResult<T> contract guarantees that ClientResult<T>.Value is non-null. " +
Expand Down Expand Up @@ -90,7 +124,11 @@ public static ClientResult<T> FromValue<T>(T value, PipelineResponse response)
/// provided <paramref name="value"/> and <paramref name="response"/>.
/// </returns>
public static ClientResult<T?> FromOptionalValue<T>(T? value, PipelineResponse response)
=> new ClientResult<T?>(value, response);
{
Argument.AssertNotNull(response, nameof(response));

return new ClientResult<T?>(value, response);
}

#endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.ClientModel.Primitives;
using System.Collections;
using System.Collections.Generic;

namespace System.ClientModel;

#pragma warning disable CS1591 // public XML comments
public abstract class ClientResultCollection<T> : ClientResult, IEnumerable<T>
{
protected internal ClientResultCollection(PipelineResponse response) : base(response)
{
}

public abstract IEnumerator<T> GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
#pragma warning restore CS1591 // public XML comments
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public class PipelineResponseTests
[Test]
public void CannotCreateClientResultFromNullResponse()
{
Assert.Throws<ArgumentNullException>(() => new MockClientResult(null!));
Assert.Throws<ArgumentNullException>(() =>
{
ClientResult result = ClientResult.FromResponse(null!);
Expand Down Expand Up @@ -98,7 +97,6 @@ public void CannotCreateClientResultOfTFromNullResponse()
{
object value = new();

Assert.Throws<ArgumentNullException>(() => new MockClientResult<object>(value, null!));
Assert.Throws<ArgumentNullException>(() =>
{
ClientResult<object> result = ClientResult.FromValue(value, null!);
Expand Down