1
0
mirror of https://github.com/chylex/.NET-Community-Toolkit.git synced 2024-10-17 06:42:48 +02:00
.NET-Community-Toolkit/CommunityToolkit.Mvvm/Messaging/Messages/AsyncRequestMessage{T}.cs
2021-12-29 18:06:54 +01:00

99 lines
3.3 KiB
C#

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace CommunityToolkit.Mvvm.Messaging.Messages;
/// <summary>
/// A <see langword="class"/> for async request messages, which can either be used directly or through derived classes.
/// </summary>
/// <typeparam name="T">The type of request to make.</typeparam>
public class AsyncRequestMessage<T>
{
private Task<T>? response;
/// <summary>
/// Gets the message response.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when <see cref="HasReceivedResponse"/> is <see langword="false"/>.</exception>
public Task<T> Response
{
get
{
if (!HasReceivedResponse)
{
ThrowInvalidOperationExceptionForNoResponseReceived();
}
return this.response!;
}
}
/// <summary>
/// Gets a value indicating whether a response has already been assigned to this instance.
/// </summary>
public bool HasReceivedResponse { get; private set; }
/// <summary>
/// Replies to the current request message.
/// </summary>
/// <param name="response">The response to use to reply to the request message.</param>
/// <exception cref="InvalidOperationException">Thrown if <see cref="Response"/> has already been set.</exception>
public void Reply(T response)
{
Reply(Task.FromResult(response));
}
/// <summary>
/// Replies to the current request message.
/// </summary>
/// <param name="response">The response to use to reply to the request message.</param>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="response"/> is <see langword="null"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown if <see cref="Response"/> has already been set.</exception>
public void Reply(Task<T> response)
{
ArgumentNullException.ThrowIfNull(response);
if (HasReceivedResponse)
{
ThrowInvalidOperationExceptionForDuplicateReply();
}
HasReceivedResponse = true;
this.response = response;
}
/// <inheritdoc cref="Task{T}.GetAwaiter"/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[EditorBrowsable(EditorBrowsableState.Never)]
public TaskAwaiter<T> GetAwaiter()
{
return this.Response.GetAwaiter();
}
/// <summary>
/// Throws an <see cref="InvalidOperationException"/> when a response is not available.
/// </summary>
[DoesNotReturn]
private static void ThrowInvalidOperationExceptionForNoResponseReceived()
{
throw new InvalidOperationException("No response was received for the given request message.");
}
/// <summary>
/// Throws an <see cref="InvalidOperationException"/> when <see cref="Reply(T)"/> or <see cref="Reply(Task{T})"/> are called twice.
/// </summary>
[DoesNotReturn]
private static void ThrowInvalidOperationExceptionForDuplicateReply()
{
throw new InvalidOperationException("A response has already been issued for the current message.");
}
}