-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCommunicationPrimitives.cs
More file actions
93 lines (71 loc) · 2.66 KB
/
CommunicationPrimitives.cs
File metadata and controls
93 lines (71 loc) · 2.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
namespace ManagedCode.Communication;
public sealed class Problem
{
private readonly Dictionary<string, IReadOnlyList<string>> _validationErrors = new(StringComparer.Ordinal);
private Problem(string errorCode, string detail, int statusCode)
{
ArgumentException.ThrowIfNullOrWhiteSpace(errorCode);
ArgumentException.ThrowIfNullOrWhiteSpace(detail);
ErrorCode = errorCode;
Detail = detail;
StatusCode = statusCode;
}
public string ErrorCode { get; }
public string Detail { get; }
public int StatusCode { get; }
public IReadOnlyDictionary<string, IReadOnlyList<string>> ValidationErrors => new ReadOnlyDictionary<string, IReadOnlyList<string>>(_validationErrors);
public static Problem Create<TCode>(TCode code, string detail, int statusCode)
where TCode : struct, Enum
{
return new Problem(code.ToString(), detail, statusCode);
}
public void AddValidationError(string fieldName, string errorMessage)
{
ArgumentException.ThrowIfNullOrWhiteSpace(fieldName);
ArgumentException.ThrowIfNullOrWhiteSpace(errorMessage);
if (_validationErrors.TryGetValue(fieldName, out var existingErrors))
{
_validationErrors[fieldName] = [.. existingErrors, errorMessage];
return;
}
_validationErrors[fieldName] = [errorMessage];
}
public bool HasErrorCode<TCode>(TCode code)
where TCode : struct, Enum
{
return string.Equals(ErrorCode, code.ToString(), StringComparison.Ordinal);
}
public bool InvalidField(string fieldName)
{
ArgumentException.ThrowIfNullOrWhiteSpace(fieldName);
return _validationErrors.ContainsKey(fieldName);
}
}
[SuppressMessage(
"Design",
"CA1000:Do not declare static members on generic types",
Justification = "The result contract intentionally exposes static success/failure factories to preserve the existing lightweight communication API.")]
public sealed class Result<T>
{
private Result(T? value, Problem? problem)
{
Value = value;
Problem = problem;
}
public T? Value { get; }
public Problem? Problem { get; }
public bool IsSuccess => Problem is null;
public bool IsFailed => !IsSuccess;
public bool HasProblem => Problem is not null;
public static Result<T> Succeed(T value)
{
return new Result<T>(value, problem: null);
}
public static Result<T> Fail(Problem problem)
{
ArgumentNullException.ThrowIfNull(problem);
return new Result<T>(value: default, problem);
}
}