Skip to content

Commit 675f44f

Browse files
CopilotJamesNK
andcommitted
Rename Interaction<T> to InteractionReference<T>, add Id property and DebuggerDisplayAttribute
Co-authored-by: JamesNK <303201+JamesNK@users.noreply.github.com>
1 parent 299b970 commit 675f44f

File tree

7 files changed

+53
-45
lines changed

7 files changed

+53
-45
lines changed

playground/Stress/Stress.AppHost/InteractionCommands.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ public static IResourceBuilder<T> AddInteractionCommands<T>(this IResourceBuilde
592592
return resource;
593593
}
594594

595-
private static void RunInteractionWithDismissValues<T>(string title, Func<bool?, string, Interaction<T>> action)
595+
private static void RunInteractionWithDismissValues<T>(string title, Func<bool?, string, InteractionReference<T>> action)
596596
{
597597
// Don't wait for interactions to complete, i.e. await tasks.
598598
_ = action(null, $"{title} - ShowDismiss = null");

src/Aspire.Hosting/IInteractionService.cs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ public interface IInteractionService
3232
/// <param name="options">Optional configuration for the message box interaction.</param>
3333
/// <param name="cancellationToken">A token to cancel the operation.</param>
3434
/// <returns>
35-
/// An <see cref="Interaction{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing <c>true</c> if the user confirmed, <c>false</c> otherwise.
35+
/// An <see cref="InteractionReference{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing <c>true</c> if the user confirmed, <c>false</c> otherwise.
3636
/// </returns>
37-
Interaction<bool> PromptConfirmationAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default);
37+
InteractionReference<bool> PromptConfirmationAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default);
3838

3939
/// <summary>
4040
/// Prompts the user with a message box dialog.
@@ -44,9 +44,9 @@ public interface IInteractionService
4444
/// <param name="options">Optional configuration for the message box interaction.</param>
4545
/// <param name="cancellationToken">A token to cancel the operation.</param>
4646
/// <returns>
47-
/// An <see cref="Interaction{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing <c>true</c> if the user accepted, <c>false</c> otherwise.
47+
/// An <see cref="InteractionReference{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing <c>true</c> if the user accepted, <c>false</c> otherwise.
4848
/// </returns>
49-
Interaction<bool> PromptMessageBoxAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default);
49+
InteractionReference<bool> PromptMessageBoxAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default);
5050

5151
/// <summary>
5252
/// Prompts the user for a single text input.
@@ -58,9 +58,9 @@ public interface IInteractionService
5858
/// <param name="options">Optional configuration for the input dialog interaction.</param>
5959
/// <param name="cancellationToken">A token to cancel the operation.</param>
6060
/// <returns>
61-
/// An <see cref="Interaction{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing the user's input.
61+
/// An <see cref="InteractionReference{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing the user's input.
6262
/// </returns>
63-
Interaction<InteractionInput> PromptInputAsync(string title, string? message, string inputLabel, string placeHolder, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default);
63+
InteractionReference<InteractionInput> PromptInputAsync(string title, string? message, string inputLabel, string placeHolder, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default);
6464

6565
/// <summary>
6666
/// Prompts the user for a single input using a specified <see cref="InteractionInput"/>.
@@ -71,9 +71,9 @@ public interface IInteractionService
7171
/// <param name="options">Optional configuration for the input dialog interaction.</param>
7272
/// <param name="cancellationToken">A token to cancel the operation.</param>
7373
/// <returns>
74-
/// An <see cref="Interaction{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing the user's input.
74+
/// An <see cref="InteractionReference{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing the user's input.
7575
/// </returns>
76-
Interaction<InteractionInput> PromptInputAsync(string title, string? message, InteractionInput input, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default);
76+
InteractionReference<InteractionInput> PromptInputAsync(string title, string? message, InteractionInput input, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default);
7777

7878
/// <summary>
7979
/// Prompts the user for multiple inputs.
@@ -84,9 +84,9 @@ public interface IInteractionService
8484
/// <param name="options">Optional configuration for the input dialog interaction.</param>
8585
/// <param name="cancellationToken">A token to cancel the operation.</param>
8686
/// <returns>
87-
/// An <see cref="Interaction{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing the user's inputs as an <see cref="InteractionInputCollection"/>.
87+
/// An <see cref="InteractionReference{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing the user's inputs as an <see cref="InteractionInputCollection"/>.
8888
/// </returns>
89-
Interaction<InteractionInputCollection> PromptInputsAsync(string title, string? message, IReadOnlyList<InteractionInput> inputs, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default);
89+
InteractionReference<InteractionInputCollection> PromptInputsAsync(string title, string? message, IReadOnlyList<InteractionInput> inputs, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default);
9090

9191
/// <summary>
9292
/// Prompts the user with a notification.
@@ -96,9 +96,9 @@ public interface IInteractionService
9696
/// <param name="options">Optional configuration for the notification interaction.</param>
9797
/// <param name="cancellationToken">A token to cancel the operation.</param>
9898
/// <returns>
99-
/// An <see cref="Interaction{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing <c>true</c> if the user accepted, <c>false</c> otherwise.
99+
/// An <see cref="InteractionReference{TResult}"/> that can be awaited to get an <see cref="InteractionResult{T}"/> containing <c>true</c> if the user accepted, <c>false</c> otherwise.
100100
/// </returns>
101-
Interaction<bool> PromptNotificationAsync(string title, string message, NotificationInteractionOptions? options = null, CancellationToken cancellationToken = default);
101+
InteractionReference<bool> PromptNotificationAsync(string title, string message, NotificationInteractionOptions? options = null, CancellationToken cancellationToken = default);
102102
}
103103

104104
internal record QueueLoadOptions(
@@ -700,22 +700,30 @@ internal InteractionResult(T? data, bool canceled)
700700
/// </summary>
701701
/// <typeparam name="TResult">The type of the result returned by the interaction.</typeparam>
702702
[Experimental(InteractionService.DiagnosticId, UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
703-
public sealed class Interaction<TResult>
703+
[DebuggerDisplay("Id = {Id}, IsCompleted = {IsCompleted}")]
704+
public sealed class InteractionReference<TResult>
704705
{
706+
private static int s_nextId;
705707
private readonly Task<InteractionResult<TResult>> _resultTask;
706708
private readonly CancellationTokenSource _cancellationTokenSource;
707709

708710
/// <summary>
709-
/// Initializes a new instance of the <see cref="Interaction{TResult}"/> class.
711+
/// Initializes a new instance of the <see cref="InteractionReference{TResult}"/> class.
710712
/// </summary>
711713
/// <param name="resultTask">The task that represents the asynchronous operation.</param>
712714
/// <param name="cancellationTokenSource">The cancellation token source for the interaction.</param>
713-
public Interaction(Task<InteractionResult<TResult>> resultTask, CancellationTokenSource cancellationTokenSource)
715+
public InteractionReference(Task<InteractionResult<TResult>> resultTask, CancellationTokenSource cancellationTokenSource)
714716
{
717+
Id = Interlocked.Increment(ref s_nextId);
715718
_resultTask = resultTask;
716719
_cancellationTokenSource = cancellationTokenSource;
717720
}
718721

722+
/// <summary>
723+
/// Gets the unique identifier for this interaction.
724+
/// </summary>
725+
public int Id { get; }
726+
719727
/// <summary>
720728
/// Gets a value indicating whether the interaction has completed.
721729
/// </summary>

src/Aspire.Hosting/InteractionService.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public bool IsAvailable
5555
}
5656
}
5757

58-
public Interaction<bool> PromptConfirmationAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default)
58+
public InteractionReference<bool> PromptConfirmationAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default)
5959
{
6060
options ??= MessageBoxInteractionOptions.CreateDefault();
6161
options.Intent = MessageIntent.Confirmation;
@@ -65,7 +65,7 @@ public Interaction<bool> PromptConfirmationAsync(string title, string message, M
6565
return PromptMessageBoxCore(title, message, options, cancellationToken);
6666
}
6767

68-
public Interaction<bool> PromptMessageBoxAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default)
68+
public InteractionReference<bool> PromptMessageBoxAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default)
6969
{
7070
options ??= MessageBoxInteractionOptions.CreateDefault();
7171
options.ShowSecondaryButton ??= false;
@@ -74,7 +74,7 @@ public Interaction<bool> PromptMessageBoxAsync(string title, string message, Mes
7474
return PromptMessageBoxCore(title, message, options, cancellationToken);
7575
}
7676

77-
private Interaction<bool> PromptMessageBoxCore(string title, string message, MessageBoxInteractionOptions options, CancellationToken cancellationToken)
77+
private InteractionReference<bool> PromptMessageBoxCore(string title, string message, MessageBoxInteractionOptions options, CancellationToken cancellationToken)
7878
{
7979
EnsureServiceAvailable();
8080

@@ -105,10 +105,10 @@ private Interaction<bool> PromptMessageBoxCore(string title, string message, Mes
105105
}
106106
}, interactionCts.Token);
107107

108-
return new Interaction<bool>(resultTask, interactionCts);
108+
return new InteractionReference<bool>(resultTask, interactionCts);
109109
}
110110

111-
public Interaction<InteractionInput> PromptInputAsync(string title, string? message, string inputLabel, string placeHolder, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
111+
public InteractionReference<InteractionInput> PromptInputAsync(string title, string? message, string inputLabel, string placeHolder, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
112112
{
113113
var interaction = PromptInputsAsync(title, message, [new InteractionInput { Name = InteractionHelpers.LabelToName(inputLabel), InputType = InputType.Text, Label = inputLabel, Required = true, Placeholder = placeHolder }], options, cancellationToken);
114114

@@ -125,10 +125,10 @@ public Interaction<InteractionInput> PromptInputAsync(string title, string? mess
125125
}, cancellationToken);
126126

127127
// Use the same CTS from the inputs interaction
128-
return new Interaction<InteractionInput>(resultTask, interaction.GetCancellationTokenSource());
128+
return new InteractionReference<InteractionInput>(resultTask, interaction.GetCancellationTokenSource());
129129
}
130130

131-
public Interaction<InteractionInput> PromptInputAsync(string title, string? message, InteractionInput input, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
131+
public InteractionReference<InteractionInput> PromptInputAsync(string title, string? message, InteractionInput input, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
132132
{
133133
var interaction = PromptInputsAsync(title, message, [input], options, cancellationToken);
134134

@@ -145,10 +145,10 @@ public Interaction<InteractionInput> PromptInputAsync(string title, string? mess
145145
}, cancellationToken);
146146

147147
// Use the same CTS from the inputs interaction
148-
return new Interaction<InteractionInput>(resultTask, interaction.GetCancellationTokenSource());
148+
return new InteractionReference<InteractionInput>(resultTask, interaction.GetCancellationTokenSource());
149149
}
150150

151-
public Interaction<InteractionInputCollection> PromptInputsAsync(string title, string? message, IReadOnlyList<InteractionInput> inputs, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
151+
public InteractionReference<InteractionInputCollection> PromptInputsAsync(string title, string? message, IReadOnlyList<InteractionInput> inputs, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
152152
{
153153
EnsureServiceAvailable();
154154

@@ -247,10 +247,10 @@ public Interaction<InteractionInputCollection> PromptInputsAsync(string title, s
247247
}
248248
}, interactionCts.Token);
249249

250-
return new Interaction<InteractionInputCollection>(resultTask, interactionCts);
250+
return new InteractionReference<InteractionInputCollection>(resultTask, interactionCts);
251251
}
252252

253-
public Interaction<bool> PromptNotificationAsync(string title, string message, NotificationInteractionOptions? options = null, CancellationToken cancellationToken = default)
253+
public InteractionReference<bool> PromptNotificationAsync(string title, string message, NotificationInteractionOptions? options = null, CancellationToken cancellationToken = default)
254254
{
255255
EnsureServiceAvailable();
256256

@@ -280,7 +280,7 @@ public Interaction<bool> PromptNotificationAsync(string title, string message, N
280280
}
281281
}, interactionCts.Token);
282282

283-
return new Interaction<bool>(resultTask, interactionCts);
283+
return new InteractionReference<bool>(resultTask, interactionCts);
284284
}
285285

286286
// For testing.

src/Shared/RequiredCommandValidator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ internal abstract class RequiredCommandValidator(IInteractionService interaction
2626
private readonly IInteractionService _interactionService = interactionService;
2727
private readonly ILogger _logger = logger;
2828

29-
private Interaction<bool>? _notificationTask;
29+
private InteractionReference<bool>? _notificationTask;
3030
private string? _notificationMessage;
3131
private bool _throwOnFailure = true;
3232

tests/Aspire.Hosting.DevTunnels.Tests/DevTunnelCliInstallationManagerTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,32 +48,32 @@ private sealed class TestInteractionService : IInteractionService
4848
{
4949
public bool IsAvailable => true;
5050

51-
public Interaction<bool> PromptConfirmationAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default)
51+
public InteractionReference<bool> PromptConfirmationAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default)
5252
{
5353
throw new NotImplementedException();
5454
}
5555

56-
public Interaction<InteractionInput> PromptInputAsync(string title, string? message, string inputLabel, string placeHolder, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
56+
public InteractionReference<InteractionInput> PromptInputAsync(string title, string? message, string inputLabel, string placeHolder, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
5757
{
5858
throw new NotImplementedException();
5959
}
6060

61-
public Interaction<InteractionInput> PromptInputAsync(string title, string? message, InteractionInput input, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
61+
public InteractionReference<InteractionInput> PromptInputAsync(string title, string? message, InteractionInput input, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
6262
{
6363
throw new NotImplementedException();
6464
}
6565

66-
public Interaction<InteractionInputCollection> PromptInputsAsync(string title, string? message, IReadOnlyList<InteractionInput> inputs, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
66+
public InteractionReference<InteractionInputCollection> PromptInputsAsync(string title, string? message, IReadOnlyList<InteractionInput> inputs, InputsDialogInteractionOptions? options = null, CancellationToken cancellationToken = default)
6767
{
6868
throw new NotImplementedException();
6969
}
7070

71-
public Interaction<bool> PromptMessageBoxAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default)
71+
public InteractionReference<bool> PromptMessageBoxAsync(string title, string message, MessageBoxInteractionOptions? options = null, CancellationToken cancellationToken = default)
7272
{
7373
throw new NotImplementedException();
7474
}
7575

76-
public Interaction<bool> PromptNotificationAsync(string title, string message, NotificationInteractionOptions? options = null, CancellationToken cancellationToken = default)
76+
public InteractionReference<bool> PromptNotificationAsync(string title, string message, NotificationInteractionOptions? options = null, CancellationToken cancellationToken = default)
7777
{
7878
throw new NotImplementedException();
7979
}

tests/Shared/AsyncTestHelpers.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public static Task<T> DefaultTimeout<T>(this ValueTask<T> task, TimeSpan timeout
125125

126126
#pragma warning disable ASPIREINTERACTION001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
127127

128-
public static Task<Aspire.Hosting.InteractionResult<T>> DefaultTimeout<T>(this Aspire.Hosting.Interaction<T> interaction, int milliseconds = -1, [CallerFilePath] string? filePath = null, [CallerLineNumber] int lineNumber = default)
128+
public static Task<Aspire.Hosting.InteractionResult<T>> DefaultTimeout<T>(this Aspire.Hosting.InteractionReference<T> interaction, int milliseconds = -1, [CallerFilePath] string? filePath = null, [CallerLineNumber] int lineNumber = default)
129129
{
130130
if (milliseconds == -1)
131131
{
@@ -135,7 +135,7 @@ public static Task<T> DefaultTimeout<T>(this ValueTask<T> task, TimeSpan timeout
135135
return interaction.GetResultAsync().TimeoutAfter(TimeSpan.FromMilliseconds(milliseconds), filePath, lineNumber);
136136
}
137137

138-
public static Task<Aspire.Hosting.InteractionResult<T>> DefaultTimeout<T>(this Aspire.Hosting.Interaction<T> interaction, TimeSpan timeout, [CallerFilePath] string? filePath = null, [CallerLineNumber] int lineNumber = default)
138+
public static Task<Aspire.Hosting.InteractionResult<T>> DefaultTimeout<T>(this Aspire.Hosting.InteractionReference<T> interaction, TimeSpan timeout, [CallerFilePath] string? filePath = null, [CallerLineNumber] int lineNumber = default)
139139
{
140140
return interaction.GetResultAsync().TimeoutAfter(timeout, filePath, lineNumber);
141141
}

0 commit comments

Comments
 (0)