Skip to content

Commit e542e9f

Browse files
Changes after Tonys suggestion
1 parent 7c173f4 commit e542e9f

File tree

5 files changed

+51
-78
lines changed

5 files changed

+51
-78
lines changed

src/OneBitSoftware.Utilities.OperationResult/Errors/IOperationError.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,5 @@ public interface IOperationError
99
string? Message { get; set; }
1010

1111
string? Details { get; set; }
12-
13-
/// <summary>
14-
/// Defines if the error is logged or not. Used when merging <cref="OperationResult"/> instances and one of them does not have an ILogger.
15-
/// </summary>
16-
bool Logged { get; internal set; }
17-
18-
/// <summary>
19-
/// Defines the log level for the error.
20-
/// </summary>
21-
LogLevel? LogLevel { get; set; }
2212
}
2313
}

src/OneBitSoftware.Utilities.OperationResult/Errors/OperationError.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55

66
public class OperationError : IOperationError
77
{
8-
public OperationError(string? message = null, int? code = null, string? details = null, LogLevel? logLevel = null)
8+
public OperationError(string? message = null, int? code = null, string? details = null)
99
{
1010
this.Message = message;
1111
this.Code = code;
1212
this.Details = details;
13-
this.LogLevel = logLevel;
1413
}
1514

1615
public int? Code { get; set; }
@@ -19,20 +18,12 @@ public OperationError(string? message = null, int? code = null, string? details
1918

2019
public string? Details { get; set; }
2120

22-
/// <inheritdoc />
23-
public LogLevel? LogLevel { get; set; }
24-
25-
/// <inheritdoc />
26-
bool IOperationError.Logged { get; set; }
27-
2821
public override string ToString()
2922
{
3023
var result = new StringBuilder();
3124

3225
if (this.Code != null) result.AppendLine($"Code: {this.Code}");
3326

34-
if (this.LogLevel is not null) result.AppendLine($"Severity: {this.LogLevel}"); // TODO: maybe convert to string?
35-
3627
if (!string.IsNullOrWhiteSpace(this.Message)) result.AppendLine($"Message: {this.Message}");
3728

3829
if (!string.IsNullOrWhiteSpace(this.Details)) result.AppendLine($"Trace: {this.Details}");

src/OneBitSoftware.Utilities.OperationResult/OperationResult.cs

Lines changed: 46 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@
1313
/// </summary>
1414
public class OperationResult
1515
{
16-
private readonly List<string> _successMessages = new List<string>();
16+
/// <summary>
17+
/// Contains <see cref="IOperationError"/> instances that have not been logged.
18+
/// </summary>
19+
private readonly List<(IOperationError Error, LogLevel? LogLevel)> _errorsNotLogged = new();
20+
21+
private readonly List<string> _successMessages = new();
1722

18-
protected readonly ILogger? _logger;
23+
private readonly ILogger? _logger;
1924

2025
/// <summary>
2126
/// Gets or sets a value indicating whether the operation is successful or not.
@@ -44,7 +49,7 @@ public IEnumerable<string>? SuccessMessages
4449
/// Gets an <see cref="List{T}"/> containing the error codes and messages of the <see cref="OperationResult{T}" />.
4550
/// </summary>
4651
public List<IOperationError> Errors { get; internal set; } = new List<IOperationError>();
47-
52+
4853
/// <summary>
4954
/// Gets or sets the first exception that resulted from the operation.
5055
/// </summary>
@@ -93,18 +98,22 @@ public OperationResult AppendErrors(OperationResult otherOperationResult)
9398
{
9499
if (otherOperationResult is null) return this;
95100

96-
foreach (var error in otherOperationResult.Errors)
101+
// store any messages for logging at a later stage, when merged to an OperationResult with a logger.
102+
if (this._logger is null)
103+
{
104+
this._errorsNotLogged.AddRange(otherOperationResult._errorsNotLogged);
105+
}
106+
else
97107
{
98-
this.AppendErrorInternal(error);
99-
100-
// Logs messages if the other operation result does not have a logger
101-
if (this._logger is not null && otherOperationResult._logger is null && !error.Logged)
102-
{
103-
this._logger.Log(GetLogLevel(error.LogLevel), error.Message);
104-
error.Logged = true;
105-
}
108+
foreach (var (error, logLevel) in otherOperationResult._errorsNotLogged)
109+
this.LogInternal(error, logLevel);
110+
111+
otherOperationResult._errorsNotLogged.Clear();
106112
}
107113

114+
// Append the error message without logging (presuming that there is already a log message).
115+
foreach (var error in otherOperationResult.Errors) this.AppendErrorInternal(error);
116+
108117
return this;
109118
}
110119

@@ -120,7 +129,7 @@ public OperationResult AppendError(string message, int? code = null, LogLevel? l
120129
{
121130
if (string.IsNullOrWhiteSpace(message)) throw new ArgumentNullException(nameof(message));
122131

123-
var error = new OperationError(message, code) { Details = details, LogLevel = logLevel };
132+
var error = new OperationError(message, code) { Details = details };
124133
this.AppendError(error, logLevel);
125134

126135
return this;
@@ -140,7 +149,7 @@ public OperationResult AppendError<T>(string message, int? code = null, LogLevel
140149
{
141150
if (string.IsNullOrWhiteSpace(message)) throw new ArgumentNullException(nameof(message));
142151

143-
var error = new T() { Message = message, Code = code, Details = details, LogLevel = logLevel };
152+
var error = new T() { Message = message, Code = code, Details = details };
144153
this.AppendError(error, logLevel);
145154

146155
return this;
@@ -155,31 +164,26 @@ public OperationResult AppendError<T>(string message, int? code = null, LogLevel
155164
public OperationResult AppendError(IOperationError error, LogLevel? logLevel = LogLevel.Error)
156165
{
157166
this.AppendErrorInternal(error);
158-
159-
if (this._logger != null)
160-
{
161-
this._logger.Log(GetLogLevel(logLevel), error.Message);
162-
error.Logged = true;
163-
}
167+
this.LogInternal(error, logLevel);
164168

165169
return this;
166170
}
167171

168172
/// <summary>
169-
/// Appends an exception to the error message collection and logs the full exception as an Error <see cref="LogEventLevel"/> level. A call to this method will set the Success property to false.
173+
/// Appends an exception to the error message collection and logs the full exception as an Error <see cref="LogLevel"/> level. A call to this method will set the Success property to false.
170174
/// </summary>
171175
/// <param name="exception">The exception to log.</param>
172176
/// <param name="errorCode">The error code.</param>
173-
/// <param name="logLevel">The <see cref="LogEventLevel"/> logging severity.</param>
177+
/// <param name="logLevel">The <see cref="LogLevel"/> logging severity.</param>
174178
/// <returns>The current instance of the <see cref="OperationResult"/>.</returns>
175-
public OperationResult AppendException(Exception exception, int? errorCode = null, LogLevel? logLevel = null)
179+
public OperationResult AppendException(Exception exception, int errorCode = 0, LogLevel? logLevel = null)
176180
{
177181
if (exception is null) throw new ArgumentNullException(nameof(exception));
178182

179183
// Append the exception as a first if it is not yet set.
180184
this.InitialException ??= exception;
181185

182-
var error = new OperationError(exception.ToString(), errorCode, null, LogLevel.Error);
186+
var error = new OperationError(exception.ToString(), errorCode);
183187
this.AppendError(error, logLevel);
184188

185189
return this;
@@ -218,13 +222,28 @@ public static OperationResult FromError(string message, int? code = null, LogLev
218222
return result.AppendError(message, code, logLevel, details);
219223
}
220224

221-
protected static LogLevel GetLogLevel(LogLevel? optionalLevel) => optionalLevel ?? LogLevel.Error;
222-
223225
/// <summary>
224226
/// Appends an <see cref="IOperationError"/> to the internal errors collection.
225227
/// </summary>
226228
/// <param name="error">An instance of <see cref="IOperationError"/> to add to the internal errors collection.</param>
227229
protected void AppendErrorInternal(IOperationError error) => this.Errors.Add(error);
230+
231+
/// <summary>
232+
/// Logs to the internal logger if it is set, otherwise it will add the error to the internal errors collection.
233+
/// </summary>
234+
/// <param name="error">The <see cref="IOperationError"/> to log.</param>
235+
/// <param name="logLevel">The log level.</param>
236+
private void LogInternal(IOperationError error, LogLevel? logLevel)
237+
{
238+
if (this._logger is null)
239+
{
240+
this._errorsNotLogged.Add((Error: error, LogLevel: logLevel));
241+
}
242+
else
243+
{
244+
this._logger.Log(logLevel ?? LogLevel.Error, error.Message);
245+
}
246+
}
228247
}
229248

230249
/// <summary>
@@ -291,41 +310,14 @@ public OperationResult(TResult resultObject) : base()
291310
return this;
292311
}
293312

294-
/// <summary>
295-
/// Appends error messages from <paramref name="otherOperationResult"/> to the current instance.
296-
/// </summary>
297-
/// <param name="otherOperationResult">The <see cref="OperationResult"/> to append from.</param>
298-
/// <typeparam name="TOther">A type that inherits from <see cref="OperationResult"/>.</typeparam>
299-
/// <returns>The original <see cref="OperationResult"/> with the appended messages from <paramref name="otherOperationResult"/>.</returns>
300-
[Obsolete("Please use AppendErrors instead. This method will be removed to avoid confusion.")]
301-
public OperationResult<TResult> AppendErrorMessages<TOther>(TOther otherOperationResult)
302-
where TOther : OperationResult
303-
{
304-
base.AppendErrors(otherOperationResult);
305-
306-
return this;
307-
}
308-
309-
/// <summary>
310-
/// Appends error from <paramref name="otherOperationResult"/> to the current instance.
311-
/// </summary>
312-
/// <param name="otherOperationResult">The <see cref="OperationResult"/> to append from.</param>
313-
/// <returns>The original <see cref="OperationResult"/> with the appended messages from <paramref name="otherOperationResult"/>.</returns>
314-
public new OperationResult<TResult> AppendErrors(OperationResult otherOperationResult)
315-
{
316-
base.AppendErrors(otherOperationResult);
317-
318-
return this;
319-
}
320-
321313
/// <summary>
322314
/// Appends an exception to the error message collection and logs the full exception as an Error <see cref="LogEventLevel"/> level. A call to this method will set the Success property to false.
323315
/// </summary>
324316
/// <param name="exception">The exception to log.</param>
325317
/// <param name="errorCode">The error code.</param>
326318
/// <param name="logLevel">The <see cref="LogEventLevel"/> logging severity.</param>
327319
/// <returns>The current instance of the <see cref="OperationResult{TResult}"/>.</returns>
328-
public new OperationResult<TResult> AppendException(Exception exception, int? errorCode = null, LogLevel? logLevel = null)
320+
public new OperationResult<TResult> AppendException(Exception exception, int errorCode = 0, LogLevel? logLevel = null)
329321
{
330322
base.AppendException(exception, errorCode, logLevel);
331323

tests/OneBitSoftware.Utilities.OperationResultTests/OperationResultAppendErrorsTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void AppendErrorsT_ShouldListAllErrors()
6262
operationResultBase.AppendError(message2, errorCode2, LogLevel.Debug, detail2);
6363

6464
// Act - AppendErrorMessages is to be removed
65-
operationResultBase.AppendErrorMessages(operationResultTarget);
65+
operationResultBase.AppendErrors(operationResultTarget);
6666

6767
// Assert
6868
Assert.False(operationResultBase.Success);

tests/OneBitSoftware.Utilities.OperationResultTests/Serialization/OperationResultSerializationSystemTextJsonTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public async Task SerializeWithSystemTextJsonIncludesTypeDiscriminator()
5656
// Assert
5757
Assert.Contains(testText, text);
5858
Assert.Contains(operationErrorText, text);
59-
var expectText = @"{""Success"":false,""Errors"":[{""type"":""operation_error"",""Code"":123,""Message"":""Test"",""Details"":""\u0022type\u0022"",""LogLevel"":null}]}";
59+
var expectText = @"{""Success"":false,""Errors"":[{""type"":""operation_error"",""Code"":123,""Message"":""Test"",""Details"":""\u0022type\u0022""}]}";
6060
Assert.Equal(expectText, text);
6161
}
6262

@@ -67,15 +67,15 @@ public async Task SerializeWithSystemTextJsonSetsExpectedJson()
6767
var testText = "\"type\"";
6868
var outputStream = new MemoryStream();
6969
var operationResult = new OperationResult();
70-
operationResult.AppendError(new OperationError(message: "Test") { Code = 123, Details = testText, LogLevel = Microsoft.Extensions.Logging.LogLevel.Warning });
70+
operationResult.AppendError(new OperationError(message: "Test") { Code = 123, Details = testText });
7171

7272
// Act
7373
await JsonSerializer.SerializeAsync(outputStream, operationResult, GetSerializationOptions());
7474
outputStream.Position = 0;
7575
string text = new StreamReader(outputStream).ReadToEnd();
7676

7777
// Assert
78-
var expectText = @"{""Success"":false,""Errors"":[{""type"":""operation_error"",""Code"":123,""Message"":""Test"",""Details"":""\u0022type\u0022"",""LogLevel"":3}]}";
78+
var expectText = @"{""Success"":false,""Errors"":[{""type"":""operation_error"",""Code"":123,""Message"":""Test"",""Details"":""\u0022type\u0022""}]}";
7979
Assert.Equal(expectText, text);
8080
}
8181

0 commit comments

Comments
 (0)