diff --git a/src/OpenFeature/Model/FlagEvaluationDetails.cs b/src/OpenFeature/Model/FlagEvaluationDetails.cs index 9af2f4bf..11283b4f 100644 --- a/src/OpenFeature/Model/FlagEvaluationDetails.cs +++ b/src/OpenFeature/Model/FlagEvaluationDetails.cs @@ -1,29 +1,29 @@ using OpenFeature.Constant; namespace OpenFeature.Model -{ +{ /// /// The contract returned to the caller that describes the result of the flag evaluation process. /// /// Flag value type /// - public sealed class FlagEvaluationDetails - { + public sealed class FlagEvaluationDetails + { /// /// Feature flag evaluated value /// - public T Value { get; } - + public T Value { get; } + /// /// Feature flag key /// - public string FlagKey { get; } - + public string FlagKey { get; } + /// /// Error that occurred during evaluation /// - public ErrorType ErrorType { get; } - + public ErrorType ErrorType { get; } + /// /// Message containing additional details about an error. /// @@ -31,25 +31,25 @@ public sealed class FlagEvaluationDetails /// details. /// /// - public string? ErrorMessage { get; } - + public string? ErrorMessage { get; } + /// /// Describes the reason for the outcome of the evaluation process /// - public string? Reason { get; } - + public string? Reason { get; } + /// /// A variant is a semantic identifier for a value. This allows for referral to particular values without /// necessarily including the value itself, which may be quite prohibitively large or otherwise unsuitable /// in some cases. /// - public string? Variant { get; } - + public string? Variant { get; } + /// /// A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number. /// - public FlagMetadata? FlagMetadata { get; } - + public ImmutableMetadata? FlagMetadata { get; } + /// /// Initializes a new instance of the class. /// @@ -60,16 +60,16 @@ public sealed class FlagEvaluationDetails /// Variant /// Error message /// Flag metadata - public FlagEvaluationDetails(string flagKey, T value, ErrorType errorType, string? reason, string? variant, - string? errorMessage = null, FlagMetadata? flagMetadata = null) - { - this.Value = value; - this.FlagKey = flagKey; - this.ErrorType = errorType; - this.Reason = reason; - this.Variant = variant; - this.ErrorMessage = errorMessage; - this.FlagMetadata = flagMetadata; - } + public FlagEvaluationDetails(string flagKey, T value, ErrorType errorType, string? reason, string? variant, + string? errorMessage = null, ImmutableMetadata? flagMetadata = null) + { + this.Value = value; + this.FlagKey = flagKey; + this.ErrorType = errorType; + this.Reason = reason; + this.Variant = variant; + this.ErrorMessage = errorMessage; + this.FlagMetadata = flagMetadata; + } } } diff --git a/src/OpenFeature/Model/FlagMetadata.cs b/src/OpenFeature/Model/FlagMetadata.cs deleted file mode 100644 index 0fddbdd3..00000000 --- a/src/OpenFeature/Model/FlagMetadata.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; - -namespace OpenFeature.Model; - -/// -/// Represents the metadata associated with a feature flag. -/// -/// -public sealed class FlagMetadata : BaseMetadata -{ - /// - /// Constructor for the class. - /// - public FlagMetadata() : this([]) - { - } - - /// - /// Constructor for the class. - /// - /// The dictionary containing the metadata. - public FlagMetadata(Dictionary metadata) : base(metadata) - { - } -} diff --git a/src/OpenFeature/Model/BaseMetadata.cs b/src/OpenFeature/Model/ImmutableMetadata.cs similarity index 67% rename from src/OpenFeature/Model/BaseMetadata.cs rename to src/OpenFeature/Model/ImmutableMetadata.cs index 876247df..40d452d0 100644 --- a/src/OpenFeature/Model/BaseMetadata.cs +++ b/src/OpenFeature/Model/ImmutableMetadata.cs @@ -1,16 +1,31 @@ using System.Collections.Generic; using System.Collections.Immutable; +#nullable enable namespace OpenFeature.Model; /// -/// Represents the base class for metadata objects. +/// Represents immutable metadata associated with feature flags and events. /// -public abstract class BaseMetadata +/// +/// +public sealed class ImmutableMetadata { private readonly ImmutableDictionary _metadata; - internal BaseMetadata(Dictionary metadata) + /// + /// Constructor for the class. + /// + public ImmutableMetadata() + { + this._metadata = ImmutableDictionary.Empty; + } + + /// + /// Constructor for the class. + /// + /// The dictionary containing the metadata. + public ImmutableMetadata(Dictionary metadata) { this._metadata = metadata.ToImmutableDictionary(); } @@ -20,7 +35,7 @@ internal BaseMetadata(Dictionary metadata) /// /// The key of the value to retrieve. /// The boolean value associated with the key, or null if the key is not found. - public virtual bool? GetBool(string key) + public bool? GetBool(string key) { return this.GetValue(key); } @@ -30,7 +45,7 @@ internal BaseMetadata(Dictionary metadata) /// /// The key of the value to retrieve. /// The integer value associated with the key, or null if the key is not found. - public virtual int? GetInt(string key) + public int? GetInt(string key) { return this.GetValue(key); } @@ -40,7 +55,7 @@ internal BaseMetadata(Dictionary metadata) /// /// The key of the value to retrieve. /// The double value associated with the key, or null if the key is not found. - public virtual double? GetDouble(string key) + public double? GetDouble(string key) { return this.GetValue(key); } @@ -50,7 +65,7 @@ internal BaseMetadata(Dictionary metadata) /// /// The key of the value to retrieve. /// The string value associated with the key, or null if the key is not found. - public virtual string? GetString(string key) + public string? GetString(string key) { var hasValue = this._metadata.TryGetValue(key, out var value); if (!hasValue) diff --git a/src/OpenFeature/Model/ProviderEvents.cs b/src/OpenFeature/Model/ProviderEvents.cs index 6feccfb0..5c48fc19 100644 --- a/src/OpenFeature/Model/ProviderEvents.cs +++ b/src/OpenFeature/Model/ProviderEvents.cs @@ -36,7 +36,6 @@ public class ProviderEventPayload /// /// Metadata information for the event. /// - // TODO: This needs to be changed to a EventMetadata object - public Dictionary? EventMetadata { get; set; } + public ImmutableMetadata? EventMetadata { get; set; } } } diff --git a/src/OpenFeature/Model/ResolutionDetails.cs b/src/OpenFeature/Model/ResolutionDetails.cs index 5f686d47..78b907d2 100644 --- a/src/OpenFeature/Model/ResolutionDetails.cs +++ b/src/OpenFeature/Model/ResolutionDetails.cs @@ -1,54 +1,54 @@ using OpenFeature.Constant; namespace OpenFeature.Model -{ +{ /// /// Defines the contract that the is required to return /// Describes the details of the feature flag being evaluated /// /// Flag value type /// - public sealed class ResolutionDetails - { + public sealed class ResolutionDetails + { /// /// Feature flag evaluated value /// - public T Value { get; } - + public T Value { get; } + /// /// Feature flag key /// - public string FlagKey { get; } - + public string FlagKey { get; } + /// /// Error that occurred during evaluation /// /// - public ErrorType ErrorType { get; } - + public ErrorType ErrorType { get; } + /// /// Message containing additional details about an error. /// - public string? ErrorMessage { get; } - + public string? ErrorMessage { get; } + /// /// Describes the reason for the outcome of the evaluation process /// /// - public string? Reason { get; } - + public string? Reason { get; } + /// /// A variant is a semantic identifier for a value. This allows for referral to particular values without /// necessarily including the value itself, which may be quite prohibitively large or otherwise unsuitable /// in some cases. /// - public string? Variant { get; } - + public string? Variant { get; } + /// /// A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number. /// - public FlagMetadata? FlagMetadata { get; } - + public ImmutableMetadata? FlagMetadata { get; } + /// /// Initializes a new instance of the class. /// @@ -59,16 +59,16 @@ public sealed class ResolutionDetails /// Variant /// Error message /// Flag metadata - public ResolutionDetails(string flagKey, T value, ErrorType errorType = ErrorType.None, string? reason = null, - string? variant = null, string? errorMessage = null, FlagMetadata? flagMetadata = null) - { - this.Value = value; - this.FlagKey = flagKey; - this.ErrorType = errorType; - this.Reason = reason; - this.Variant = variant; - this.ErrorMessage = errorMessage; - this.FlagMetadata = flagMetadata; - } + public ResolutionDetails(string flagKey, T value, ErrorType errorType = ErrorType.None, string? reason = null, + string? variant = null, string? errorMessage = null, ImmutableMetadata? flagMetadata = null) + { + this.Value = value; + this.FlagKey = flagKey; + this.ErrorType = errorType; + this.Reason = reason; + this.Variant = variant; + this.ErrorMessage = errorMessage; + this.FlagMetadata = flagMetadata; + } } } diff --git a/test/OpenFeature.Tests/FlagMetadataTest.cs b/test/OpenFeature.Tests/ImmutableMetadataTest.cs similarity index 91% rename from test/OpenFeature.Tests/FlagMetadataTest.cs rename to test/OpenFeature.Tests/ImmutableMetadataTest.cs index d716d91e..344392b0 100644 --- a/test/OpenFeature.Tests/FlagMetadataTest.cs +++ b/test/OpenFeature.Tests/ImmutableMetadataTest.cs @@ -5,7 +5,7 @@ namespace OpenFeature.Tests; -public class FlagMetadataTest +public class ImmutableMetadataTest { [Fact] [Specification("1.4.14", @@ -13,7 +13,7 @@ public class FlagMetadataTest public void GetBool_Should_Return_Null_If_Key_Not_Found() { // Arrange - var flagMetadata = new FlagMetadata(); + var flagMetadata = new ImmutableMetadata(); // Act var result = flagMetadata.GetBool("nonexistentKey"); @@ -35,7 +35,7 @@ public void GetBool_Should_Return_Value_If_Key_Found() "boolKey", true } }; - var flagMetadata = new FlagMetadata(metadata); + var flagMetadata = new ImmutableMetadata(metadata); // Act var result = flagMetadata.GetBool("boolKey"); @@ -56,7 +56,7 @@ public void GetBool_Should_Throw_Value_Is_Invalid() "wrongKey", "11a" } }; - var flagMetadata = new FlagMetadata(metadata); + var flagMetadata = new ImmutableMetadata(metadata); // Act var result = flagMetadata.GetBool("wrongKey"); @@ -71,7 +71,7 @@ public void GetBool_Should_Throw_Value_Is_Invalid() public void GetInt_Should_Return_Null_If_Key_Not_Found() { // Arrange - var flagMetadata = new FlagMetadata(); + var flagMetadata = new ImmutableMetadata(); // Act var result = flagMetadata.GetInt("nonexistentKey"); @@ -93,7 +93,7 @@ public void GetInt_Should_Return_Value_If_Key_Found() "intKey", 1 } }; - var flagMetadata = new FlagMetadata(metadata); + var flagMetadata = new ImmutableMetadata(metadata); // Act var result = flagMetadata.GetInt("intKey"); @@ -115,7 +115,7 @@ public void GetInt_Should_Throw_Value_Is_Invalid() "wrongKey", "11a" } }; - var flagMetadata = new FlagMetadata(metadata); + var flagMetadata = new ImmutableMetadata(metadata); // Act var result = flagMetadata.GetInt("wrongKey"); @@ -130,7 +130,7 @@ public void GetInt_Should_Throw_Value_Is_Invalid() public void GetDouble_Should_Return_Null_If_Key_Not_Found() { // Arrange - var flagMetadata = new FlagMetadata(); + var flagMetadata = new ImmutableMetadata(); // Act var result = flagMetadata.GetDouble("nonexistentKey"); @@ -152,7 +152,7 @@ public void GetDouble_Should_Return_Value_If_Key_Found() "doubleKey", 1.2 } }; - var flagMetadata = new FlagMetadata(metadata); + var flagMetadata = new ImmutableMetadata(metadata); // Act var result = flagMetadata.GetDouble("doubleKey"); @@ -174,7 +174,7 @@ public void GetDouble_Should_Throw_Value_Is_Invalid() "wrongKey", "11a" } }; - var flagMetadata = new FlagMetadata(metadata); + var flagMetadata = new ImmutableMetadata(metadata); // Act var result = flagMetadata.GetDouble("wrongKey"); @@ -189,7 +189,7 @@ public void GetDouble_Should_Throw_Value_Is_Invalid() public void GetString_Should_Return_Null_If_Key_Not_Found() { // Arrange - var flagMetadata = new FlagMetadata(); + var flagMetadata = new ImmutableMetadata(); // Act var result = flagMetadata.GetString("nonexistentKey"); @@ -211,7 +211,7 @@ public void GetString_Should_Return_Value_If_Key_Found() "stringKey", "11" } }; - var flagMetadata = new FlagMetadata(metadata); + var flagMetadata = new ImmutableMetadata(metadata); // Act var result = flagMetadata.GetString("stringKey"); @@ -233,7 +233,7 @@ public void GetString_Should_Throw_Value_Is_Invalid() "wrongKey", new object() } }; - var flagMetadata = new FlagMetadata(metadata); + var flagMetadata = new ImmutableMetadata(metadata); // Act var result = flagMetadata.GetString("wrongKey"); diff --git a/test/OpenFeature.Tests/OpenFeatureEventTests.cs b/test/OpenFeature.Tests/OpenFeatureEventTests.cs index 599cea30..3a373c98 100644 --- a/test/OpenFeature.Tests/OpenFeatureEventTests.cs +++ b/test/OpenFeature.Tests/OpenFeatureEventTests.cs @@ -25,12 +25,7 @@ public async Task Event_Executor_Should_Propagate_Events_ToGlobal_Handler() eventExecutor.AddApiLevelHandler(ProviderEventTypes.ProviderConfigurationChanged, eventHandler); - var eventMetadata = new Dictionary - { - { - "foo", "bar" - } - }; + var eventMetadata = new ImmutableMetadata(new Dictionary { { "foo", "bar" } }); var myEvent = new Event { EventPayload = new ProviderEventPayload