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