From 4b9652766e7f73a6ada972629c50be1fb37b8107 Mon Sep 17 00:00:00 2001 From: Brian MacKay Date: Tue, 9 Oct 2018 12:25:09 -0400 Subject: [PATCH] Bumped to 2.9.5 Fixed an issue where StatusCode was not included in FromOutcome. Changed this so that StatusCode is now backed by the Keys dictionary. Since StatusCode is a property, it should still be serialized the same way, so this is not a breaking change for the edge case where an Outcome is serialized to Json and StatusCode is expected. --- Outcomes.Tests/SuccessTests.cs | 11 ++++++-- Outcomes/Builder/FailureOutcomeBuilder.cs | 2 +- Outcomes/Builder/SuccessOutcomeBuilder.cs | 4 +-- Outcomes/OutcomeResult.cs | 32 +++++++++++++++++++++-- Outcomes/Outcomes.csproj | 4 +-- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/Outcomes.Tests/SuccessTests.cs b/Outcomes.Tests/SuccessTests.cs index b6bef06..58c0d87 100644 --- a/Outcomes.Tests/SuccessTests.cs +++ b/Outcomes.Tests/SuccessTests.cs @@ -72,14 +72,18 @@ public void Success_WithKeysFrom_Works() public void Success_FromOutcome_Persists_Values() { var outcome1 = Outcomes.Success() - .WithValue(10); + .WithValue(10) + .WithStatusCode(505); + var outcome2 = Outcomes.Success() - .WithValue(20); + .WithValue(20) + .WithStatusCode(null); //In this case, some casting is going to happen. var outcome3 = Outcomes.Success() .WithValue(new ExampleConcrete() { SomeInt = 0, SomeString = "not important" }); + //In this case, there's a null value. var outcome4 = Outcomes.Success() @@ -97,8 +101,11 @@ public void Success_FromOutcome_Persists_Values() var from5 = Outcomes.Success().FromOutcome(outcome5); Assert.True(from1.Value.Equals(10)); + Assert.True(from1.StatusCode == 505); Assert.True(from2.Value.Equals(20)); + Assert.True(from2.StatusCode == null); Assert.True(from3.Value.SomeString == "not important"); + Assert.True(from3.StatusCode == null); // not set, should be null Assert.True(from4.Value == null); Assert.True(from5.Value == null); } diff --git a/Outcomes/Builder/FailureOutcomeBuilder.cs b/Outcomes/Builder/FailureOutcomeBuilder.cs index e44a1d5..d96b4a1 100644 --- a/Outcomes/Builder/FailureOutcomeBuilder.cs +++ b/Outcomes/Builder/FailureOutcomeBuilder.cs @@ -80,7 +80,7 @@ public IFailureOutcomeBuilder FromException(Exception exception) return this; } - [Obsolete("This will eventually be replaced by the new Keys dictionary.")] + [Obsolete("Considering removing this in favor of the Keys dictionary, pending community feedback.")] public new IFailureOutcomeBuilder WithStatusCode(int? statusCode) { base.WithStatusCode(statusCode); diff --git a/Outcomes/Builder/SuccessOutcomeBuilder.cs b/Outcomes/Builder/SuccessOutcomeBuilder.cs index 175f60a..9b91bfc 100644 --- a/Outcomes/Builder/SuccessOutcomeBuilder.cs +++ b/Outcomes/Builder/SuccessOutcomeBuilder.cs @@ -46,7 +46,7 @@ public SuccessOutcomeBuilder WithMessage(string message) /// /// Append a list of strings to the end of the outcome's message collection. /// - /// Enum of srings to add. + /// Enum of strings to add. /// public SuccessOutcomeBuilder WithMessage(IEnumerable messages) { @@ -91,7 +91,7 @@ public SuccessOutcomeBuilder WithValue(TValue value) /// (optional) Sets the StatusCode, which is an additional piece of metadata you can use for your own purposes. /// This is handy when there could be, for instance, multiple failure modes. /// - [Obsolete("This will eventually be replaced by the new Keys dictionary.")] + [Obsolete("Considering removing this in favor of the Keys dictionary, pending community feedback.")] public SuccessOutcomeBuilder WithStatusCode(int? statusCode) { base.StatusCode = statusCode; diff --git a/Outcomes/OutcomeResult.cs b/Outcomes/OutcomeResult.cs index 5501670..24ca739 100644 --- a/Outcomes/OutcomeResult.cs +++ b/Outcomes/OutcomeResult.cs @@ -21,7 +21,36 @@ public class OutcomeResult : IOutcome public bool Success { get; protected set; } public List Messages { get; protected set; } public TValue Value { get; set; } - public int? StatusCode { get; protected set; } + + /// + /// Syntactic sugar for Keys.ContainsKey["StatusCode"]. Guarantees that StatusCode will be a nullable + /// int. If it is not, because Keys["StatusCode"] was set manually to something strange, it will return null. + /// + [Obsolete("Considering removing this in favor of the Keys dictionary, pending community feedback.")] + public int? StatusCode + { + get + { + // Since the backing field is in a Dictionary, we have to careful coerce + // it into a nullable int. + if (!Keys.ContainsKey("StatusCode")) + return null; + + var statusCode = Keys["StatusCode"]; + + if (statusCode == null) + return null; + + var statusCodeString = statusCode.ToString(); + + if (int.TryParse(statusCodeString, out var value)) + return value; + else + return null; + } + protected set => Keys["StatusCode"] = value; + } + public Dictionary Keys { get; } public bool Failure => !Success; @@ -30,7 +59,6 @@ internal OutcomeResult(bool success) Success = success; Messages = new List(); Value = default(TValue); - StatusCode = null; Keys = new Dictionary(); } diff --git a/Outcomes/Outcomes.csproj b/Outcomes/Outcomes.csproj index a229d33..406d2ca 100644 --- a/Outcomes/Outcomes.csproj +++ b/Outcomes/Outcomes.csproj @@ -9,7 +9,7 @@ Ether.Outcomes Ether.Outcomes c#;.net;notification;fluent;response;failure;success - Fixed an issue where, on the .Net Standard 1.3 target, FromOutcome() was not copying the value and the test wasn't catching it. + Fixed an issue where StatusCode was not included in FromOutcome. Changed this so that StatusCode is now backed by the Keys dictionary. Since StatusCode is a property, it should still be serialized the same way, so this is not a breaking change for the edge case where an Outcome is serialized to Json and StatusCode is expected. https://github.com/kinetiq/Ether.Outcomes http://choosealicense.com/licenses/mit/ $(PackageTargetFallback);dnxcore50 @@ -17,7 +17,7 @@ false false false - 2.9.4-beta + 2.9.5 true Brian MacKay