Skip to content

Commit

Permalink
update Orleans.Results template to 1.0.0 (NOTE this contains a breaki…
Browse files Browse the repository at this point in the history
…ng change: ErrorCode has been renamed to ErrorNr to avoid a name conflict with Orleans.ErrorCode; other members named *Code are also renames to *Nr)
  • Loading branch information
VincentH-Net committed Nov 10, 2022
1 parent 227acb3 commit 15e31da
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ Templates:
For how to install, see:<br />
[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/Modern.CSharp.Templates?color=gold&label=NuGet:%20Modern.CSharp.Templates&style=plastic)](https://www.nuget.org/packages/Modern.CSharp.Templates)

More templates are coming (in Oct 2022):
More templates are coming (in Nov 2022):
- Orleans.Multiservice (use a single Orleans service with multiple logical services inside it as an alternative to separate microservices)
- Orleans.Multitenant (uses [Orleans.Multitenant](https://github.com/Applicita/Orleans.Multitenant) to separate grain state storage and grain/stream communication per tenant)
2 changes: 1 addition & 1 deletion src/Modern.CSharp.Templates.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<PackageId>Modern.CSharp.Templates</PackageId>
<PackageVersion>1.0.0-rc2</PackageVersion>
<PackageVersion>1.0.0</PackageVersion>
<PackageType>Template</PackageType>
<Title>Modern C# 11 Templates</Title>
<Description>A toolkit of modern dotnet new templates for C# 11, .NET 7 and Microsoft Orleans 7</Description>
Expand Down
2 changes: 1 addition & 1 deletion src/Orleans.Results/.template.config/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"description": "Update namespace",
"manualInstructions": [
{
"text": "update the Example namespace in the added ErrorCode.cs and Result.cs files to match your project"
"text": "update the Example namespace in the added ErrorNr.cs and Result.cs files to match your project"
}
],
"actionId": "AC1156F7-BB77-4DB8-B28F-24EEBCCA1E5C",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Example;

[Flags]
public enum ErrorCode
public enum ErrorNr
{
UserNotFound = 1,
NoUsersAtAddress = 2,
Expand Down
46 changes: 25 additions & 21 deletions src/Orleans.Results/Result.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Version: 1.0.0-preview.2 (Using https://semver.org/)
// Updated: 2022-08-26
// Version: 1.0.0 (Using https://semver.org/)
// Updated: 2022-11-10
// See https://github.com/Applicita/Orleans.Results for updates to this file.

using System.Collections.Immutable;
Expand All @@ -9,10 +9,10 @@
namespace Example;

/// <summary>
/// Result without value; use to return either <see cref="Ok"/> or <see cref="ResultBase{ErrorCode}.Error"/>(s)
/// Result without value; use to return either <see cref="Ok"/> or <see cref="ResultBase{ErrorNr}.Error"/>(s)
/// </summary>
[GenerateSerializer, Immutable]
public class Result : ResultBase<ErrorCode>
public class Result : ResultBase<ErrorNr>
{
public static Result Ok { get; } = new();

Expand All @@ -22,16 +22,16 @@ public Result(IEnumerable<Error> errors) : base(ImmutableArray.CreateRange(error
Result(Error error) : base(error) { }

public static implicit operator Result(Error error) => new(error);
public static implicit operator Result(ErrorCode code) => new(code);
public static implicit operator Result((ErrorCode code, string message) error) => new(error);
public static implicit operator Result(ErrorNr nr) => new(nr);
public static implicit operator Result((ErrorNr nr, string message) error) => new(error);
public static implicit operator Result(List<Error> errors) => new(errors);
}

/// <summary>
/// Result with value; use to return either a <typeparamref name="TValue"/> or <see cref="ResultBase{ErrorCode}.Error"/>(s)
/// Result with value; use to return either a <typeparamref name="TValue"/> or <see cref="ResultBase{ErrorNr}.Error"/>(s)
/// </summary>
[GenerateSerializer]
public class Result<TValue> : ResultBase<ErrorCode, TValue>
public class Result<TValue> : ResultBase<ErrorNr, TValue>
{
public Result(ImmutableArray<Error> errors) : base(errors) { }
public Result(IEnumerable<Error> errors) : base(ImmutableArray.CreateRange(errors)) { }
Expand All @@ -40,13 +40,13 @@ public Result(IEnumerable<Error> errors) : base(ImmutableArray.CreateRange(error

public static implicit operator Result<TValue>(TValue value) => new(value);
public static implicit operator Result<TValue>(Error error) => new(error);
public static implicit operator Result<TValue>(ErrorCode code) => new(code);
public static implicit operator Result<TValue>((ErrorCode code, string message) error) => new(error);
public static implicit operator Result<TValue>(ErrorNr nr) => new(nr);
public static implicit operator Result<TValue>((ErrorNr nr, string message) error) => new(error);
public static implicit operator Result<TValue>(List<Error> errors) => new(errors);
}

[GenerateSerializer]
public abstract class ResultBase<TErrorCode, TValue> : ResultBase<TErrorCode> where TErrorCode : Enum
public abstract class ResultBase<TErrorNr, TValue> : ResultBase<TErrorNr> where TErrorNr : Enum
{
[Id(0)] TValue? value;

Expand Down Expand Up @@ -77,11 +77,13 @@ public TValue Value
}
}

public override string ToString() => IsSuccess ? $"{Value}" : ErrorsText;

void ThrowIfFailed() { if (IsFailed) throw new InvalidOperationException("Attempt to access the value of a failed result"); }
}

[GenerateSerializer]
public abstract class ResultBase<TErrorCode> where TErrorCode : Enum
public abstract class ResultBase<TErrorNr> where TErrorNr : Enum
{
public bool IsSuccess => !IsFailed;
public bool IsFailed => errors?.Length > 0;
Expand All @@ -95,9 +97,9 @@ public abstract class ResultBase<TErrorCode> where TErrorCode : Enum
public ImmutableArray<Error> Errors => errors ?? throw new InvalidOperationException("Attempt to access the errors of a success result");

/// <summary>
/// Returns the errorcode for a failed result with a single error; otherwise throws an exception
/// Returns the error nr for a failed result with a single error; otherwise throws an exception
/// </summary>
public TErrorCode ErrorCode => Errors.Single().Code;
public TErrorNr ErrorNr => Errors.Single().Nr;

/// <summary>
/// Returns all errors formatted in a single string for a failed result; throws an <see cref="InvalidOperationException"/> for a success result
Expand All @@ -110,21 +112,23 @@ public abstract class ResultBase<TErrorCode> where TErrorCode : Enum
/// <remarks>Intended for use with <see cref="Microsoft.AspNetCore.Mvc.ValidationProblemDetails"/> (in MVC controllers) or <see cref="Microsoft.AspNetCore.Http.Results.ValidationProblem"/> (in minimal api's) </remarks>
/// <param name="validationErrorFlag">The enum flag used to identify an error as a validation error</param>
/// <param name="validationErrors">If the return value is true, receives all errors in a dictionary suitable for serializing into a https://tools.ietf.org/html/rfc7807 based format; otherwise set to null</param>
/// <returns>True for a failed result that has the <paramref name="validationErrorFlag"/> set in the <typeparamref name="TErrorCode"/> for <b>all</b> errors; false otherwise</returns>
/// <returns>True for a failed result that has the <paramref name="validationErrorFlag"/> set in the <typeparamref name="TErrorNr"/> for <b>all</b> errors; false otherwise</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0001:Simplify Names", Justification = "Full name is necessary to ensure link works independently of global usings")]
public bool TryAsValidationErrors(TErrorCode validationErrorFlag, [NotNullWhen(true)] out Dictionary<string, string[]>? validationErrors)
public bool TryAsValidationErrors(TErrorNr validationErrorFlag, [NotNullWhen(true)] out Dictionary<string, string[]>? validationErrors)
{
if (IsFailed && Errors.All(error => error.Code.HasFlag(validationErrorFlag)))
if (IsFailed && Errors.All(error => error.Nr.HasFlag(validationErrorFlag)))
{
validationErrors = new(Errors
.GroupBy(error => error.Code, error => error.Message)
.GroupBy(error => error.Nr, error => error.Message)
.Select(group => new KeyValuePair<string, string[]>(group.Key.ToString(), group.ToArray())));
return true;
}
validationErrors = null;
return false;
}

public override string ToString() => IsSuccess ? nameof(Result.Ok) : ErrorsText;

protected ResultBase() { }
protected ResultBase(Error error) => errors = ImmutableArray.Create(error);
protected ResultBase(ImmutableArray<Error> errors) => this.errors = errors;
Expand All @@ -133,9 +137,9 @@ protected ResultBase() { }
public NotImplementedException UnhandledErrorException(string? message = null) => new($"{message}Unhandled error(s): " + ErrorsText);

[GenerateSerializer, Immutable]
public record Error([property: Id(0)] TErrorCode Code, [property: Id(1)] string Message = "")
public record Error([property: Id(0)] TErrorNr Nr, [property: Id(1)] string Message = "")
{
public static implicit operator Error(TErrorCode code) => new(code);
public static implicit operator Error((TErrorCode code, string message) error) => new(error.code, error.message);
public static implicit operator Error(TErrorNr nr) => new(nr);
public static implicit operator Error((TErrorNr nr, string message) error) => new(error.nr, error.message);
}
}
2 changes: 1 addition & 1 deletion src/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Templates:

Docs: see the [repo readme](https://github.com/Applicita/Modern.CSharp.Templates#readme)

[Release Notes](https://github.com/Applicita/Modern.CSharp.Templates/releases/tag/1-0-0-rc2)
[Release Notes](https://github.com/Applicita/Modern.CSharp.Templates/releases/tag/1-0-0)

0 comments on commit 15e31da

Please sign in to comment.