Skip to content

Refactor Result extensions, add metadata and conversion utils#132

Merged
cloudfy merged 4 commits intomainfrom
131-arcturusresultobjects-add-bag-items-to-result-to-carry-extra-data-between-layers
Feb 5, 2026
Merged

Refactor Result extensions, add metadata and conversion utils#132
cloudfy merged 4 commits intomainfrom
131-arcturusresultobjects-add-bag-items-to-result-to-carry-extra-data-between-layers

Conversation

@cloudfy
Copy link
Copy Markdown
Owner

@cloudfy cloudfy commented Feb 5, 2026

  • Refactored WithException, WithHttpStatusCode, and WithHelpLink to be generic and work with both Result and Result.
  • Added WithBag extension and BagItems property for attaching and accessing metadata on Result objects.
  • Introduced ObjectConversion utility with TryGetSuccessValue, ToSuccessResult, and ToFailureResult methods for easier value/result conversions.
  • Improved XML documentation and formatting throughout the codebase.
  • Minor .csproj cleanup for packaging and documentation.

Summary & Motivation

A brief description of the changes in this pull request explaining why these changes are necessary. Please delete this paragraph.

Checklist

  • I have added tests, or done manual regression tests
  • I have updated the documentation, if necessary

- Refactored WithException, WithHttpStatusCode, and WithHelpLink to be generic and work with both Result and Result<T>.
- Added WithBag extension and BagItems property for attaching and accessing metadata on Result objects.
- Introduced ObjectConversion utility with TryGetSuccessValue, ToSuccessResult, and ToFailureResult methods for easier value/result conversions.
- Improved XML documentation and formatting throughout the codebase.
- Minor .csproj cleanup for packaging and documentation.
@cloudfy cloudfy requested a review from Copilot February 5, 2026 12:24
@cloudfy cloudfy self-assigned this Feb 5, 2026
@cloudfy cloudfy added the enhancement New feature or request label Feb 5, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request refactors the Result object extensions to use generic type constraints, adds a metadata/property bag feature to Result objects, and introduces utility methods for converting values to Result objects.

Changes:

  • Consolidated separate Result and Result extension methods (WithException, WithHttpStatusCode, WithHelpLink) into single generic methods with where T : Result constraints
  • Added metadata storage capability through WithBag extension method and BagItems property
  • Introduced ObjectConversion utility class with TryGetSuccessValue, ToSuccessResult, and ToFailureResult helper methods
  • Enhanced XML documentation throughout
  • Minor formatting cleanup in .csproj file

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
ResultExtensions.cs Refactored extension methods to use generic type constraints, eliminating duplicate code; added new WithBag method for metadata storage
Result.cs Added internal Metadata dictionary and public BagItems property for metadata access; updated XML doc references
Conversion/ObjectConversion.cs New utility class providing conversion helpers between values and Result objects
IResultValue.cs Added XML documentation to the interface
ResultOfT.cs Removed unused System.Diagnostics.CodeAnalysis import
Arcturus.ResultObjects.csproj Minor formatting cleanup

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Arcturus.ResultObjects/Conversion/ObjectConversion.cs Outdated
/// <returns>A Result<T> instance representing a successful operation with the specified value.</returns>
public static Result<T> ToSuccessResult<T>(this T value)
{
return Result<T>.Success<T>(value);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type parameter specification '' is redundant in this static method call. The type can be inferred from the return type. This should be simplified to 'Result.Success(value)'.

Copilot uses AI. Check for mistakes.
/// <returns>A failed result of type <typeparamref name="T"/> containing the specified fault.</returns>
public static Result<T> ToFailureResult<T>(this T value, Fault? fault)
{
return Result<T>.Failure<T>(fault);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type parameter specification '' is redundant in this static method call. The type can be inferred from the return type. This should be simplified to 'Result.Failure(fault)'.

Copilot uses AI. Check for mistakes.
/// <returns>A failed result of type T containing the specified error code and message.</returns>
public static Result<T> ToFailureResult<T>(this T value, string? code, string message)
{
return Result<T>.Failure<T>(code, message);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type parameter specification '' is redundant in this static method call. The type can be inferred from the return type. This should be simplified to 'Result.Failure(code, message)'.

Copilot uses AI. Check for mistakes.
Comment thread src/Arcturus.ResultObjects/ResultExtensions.cs Outdated
Comment thread src/Arcturus.ResultObjects/ResultExtensions.cs Outdated
Comment on lines +38 to +58
/// Creates a failed result containing the specified fault for the given value.
/// </summary>
/// <typeparam name="T">The type of the value associated with the result.</typeparam>
/// <param name="value">The value to associate with the failed result. This value is not used in the failure case but is required for
/// extension method syntax.</param>
/// <param name="fault">The fault information to include in the failed result. Can be null to indicate an unspecified failure.</param>
/// <returns>A failed result of type <typeparamref name="T"/> containing the specified fault.</returns>
public static Result<T> ToFailureResult<T>(this T value, Fault? fault)
{
return Result<T>.Failure<T>(fault);
}
/// <summary>
/// Creates a failed result with the specified error code and message.
/// </summary>
/// <typeparam name="T">The type of the value associated with the result.</typeparam>
/// <param name="value">The value to associate with the failed result. This value is not used in the failure case but is required for
/// extension method syntax.</param>
/// <param name="code">The error code that identifies the reason for failure. Can be null if no code is applicable.</param>
/// <param name="message">A message describing the failure. Cannot be null.</param>
/// <returns>A failed result of type T containing the specified error code and message.</returns>
public static Result<T> ToFailureResult<T>(this T value, string? code, string message)
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'value' parameter in these ToFailureResult extension methods is misleading and unused. The methods create a failure result that doesn't use the input value at all. This API design could confuse users who might expect the value to be stored or used somehow.

Consider making these static methods on a utility class instead of extension methods, or clarifying in the documentation that the value parameter is ignored and exists only to enable extension method syntax. Alternatively, consider whether these extension methods provide sufficient value over calling Result.Failure directly.

Suggested change
/// Creates a failed result containing the specified fault for the given value.
/// </summary>
/// <typeparam name="T">The type of the value associated with the result.</typeparam>
/// <param name="value">The value to associate with the failed result. This value is not used in the failure case but is required for
/// extension method syntax.</param>
/// <param name="fault">The fault information to include in the failed result. Can be null to indicate an unspecified failure.</param>
/// <returns>A failed result of type <typeparamref name="T"/> containing the specified fault.</returns>
public static Result<T> ToFailureResult<T>(this T value, Fault? fault)
{
return Result<T>.Failure<T>(fault);
}
/// <summary>
/// Creates a failed result with the specified error code and message.
/// </summary>
/// <typeparam name="T">The type of the value associated with the result.</typeparam>
/// <param name="value">The value to associate with the failed result. This value is not used in the failure case but is required for
/// extension method syntax.</param>
/// <param name="code">The error code that identifies the reason for failure. Can be null if no code is applicable.</param>
/// <param name="message">A message describing the failure. Cannot be null.</param>
/// <returns>A failed result of type T containing the specified error code and message.</returns>
public static Result<T> ToFailureResult<T>(this T value, string? code, string message)
/// Creates a failed result containing the specified fault.
/// </summary>
/// <typeparam name="T">The type parameter of the result.</typeparam>
/// <param name="fault">The fault information to include in the failed result. Can be null to indicate an unspecified failure.</param>
/// <returns>A failed result of type <typeparamref name="T"/> containing the specified fault.</returns>
public static Result<T> ToFailureResult<T>(Fault? fault)
{
return Result<T>.Failure<T>(fault);
}
/// <summary>
/// Creates a failed result with the specified error code and message.
/// </summary>
/// <typeparam name="T">The type parameter of the result.</typeparam>
/// <param name="code">The error code that identifies the reason for failure. Can be null if no code is applicable.</param>
/// <param name="message">A message describing the failure. Cannot be null.</param>
/// <returns>A failed result of type <typeparamref name="T"/> containing the specified error code and message.</returns>
public static Result<T> ToFailureResult<T>(string? code, string message)

Copilot uses AI. Check for mistakes.
{
result.HelpLink = uri;
result.Metadata ??= [];
result.Metadata.Add(key, value);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WithBag method doesn't check if the key already exists in the metadata dictionary before adding. This will throw an ArgumentException if the same key is added twice. Consider using dictionary indexer syntax (result.Metadata[key] = value) instead of Add, which will overwrite existing values, or document that duplicate keys will throw an exception.

Suggested change
result.Metadata.Add(key, value);
result.Metadata[key] = value;

Copilot uses AI. Check for mistakes.
/// <summary>
/// Gets additional metadata items. Use <see cref="ResultExtensions.WithBag{T}(T, string, object?)"/>.
/// </summary>
public IReadOnlyDictionary<string, object?>? BagItems => Metadata;
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming is inconsistent between the method name WithBag and the property name BagItems. For consistency and clarity, consider either:

  1. Renaming WithBag to WithBagItem (matching BagItems), or
  2. Renaming to a more standard metadata terminology like WithMetadata/MetadataItems or WithProperty/Properties

The term "bag" is somewhat informal and may not clearly communicate that this is for metadata storage. Compare with EventContext in the codebase which uses "Items" for its property bag.

Suggested change
public IReadOnlyDictionary<string, object?>? BagItems => Metadata;
public IReadOnlyDictionary<string, object?>? MetadataItems => Metadata;

Copilot uses AI. Check for mistakes.
cloudfy and others added 3 commits February 5, 2026 13:29
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@cloudfy cloudfy merged commit ff5aa23 into main Feb 5, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Arcturus.ResultObjects] Add bag items to result to carry extra data between layers.

2 participants