OptimizelyConfig for the C# SDK
How to get access to project configuration data within the datafile using OptimizelyConfig for the C# SDK.
Overview
Feature Experimentation SDKs open a well-defined set of public APIs, hiding all implementation details. However, some clients may need access to project configuration data within the datafile.
In this document, we extend our public APIs to define data models and access methods, which clients can use to access project configuration data.
OptimizelyConfig API
A public configuration data model (OptimizelyConfig) is defined below as a structured format of static Optimizely Project data.
Get OptimizelyConfig
OptimizelyConfig can be accessed from OptimizelyClient (top-level) with this public API call:
public OptimizelyConfig GetOptimizelyConfig()
GetOptimizelyConfig
returns an OptimizelyConfig
instance, which includes
- environment key
- SDK key
- the datafile revision number
- all experiments mapped by their key values
- all attributes
- all audiences
- all events
- feature flags mapped by their key values
- function to retrieve the project configuration (the datafile)
Note
When the SDK datafile is updated (the client can add a notification listener for
OPTIMIZELY_CONFIG_UPDATE
to get notified), the client is expected to call the method to get the updated OptimizelyConfig data. See examples below.
Get datafile
To ensure that multiple SDK instances all instantiate from the same configuration (for example, in a client/server scenario), you can pass a JSON string representation of the config (the datafile) between the instances. To get the datafile, use the OptimizelyConfig
object's GetDatafile
method. For more information, see Sharing the datafile with multiple SDK implementations.
Object model
The following shows the object model for OptimizelyConfig.
// OptimizelyConfig is class describing the current project configuration data being used by this SDK instance.
public class OptimizelyConfig
{
public string Revision { get; private set; }
public string SDKKey { get; private set; }
public string EnvironmentKey { get; private set; }
public OptimizelyEvent[] Events { get; private set; }
public OptimizelyAudience[] Audiences { get; private set; }
public OptimizelyAttribute[] Attributes { get; private set; }
// This experimentsMap is for experiments of legacy projects only.
// For flag projects, experiment keys are not guaranteed to be unique
// across multiple flags, so this map may not include all experiments
// when keys conflict.
public IDictionary<string, OptimizelyExperiment> ExperimentsMap { get; private set; }
public IDictionary<string, OptimizelyFeature> FeaturesMap { get; private set; }
public string GetDatafile { get; private set; }
}
// Entity.IdKeyEntity is an abstract class used for inheritance in OptimizelyExperiment, OptimizelyFeature, OptimizelyVariation and OptimizelyVariable classes.
public abstract class IdKeyEntity : Entity, IEquatable<object>
{
public string Id { get; set; }
public string Key { get; set; }
}
// OptimizelyAttribute is a class describing attribute and inherited from Entity.IdKeyEntity.
public class OptimizelyAttribute : Entity.IdKeyEntity
{
}
// OptimizelyAudience is a class describing an audience.
public class OptimizelyAudience
{
public string Id { get; set; }
public string Name { get; set; }
public object Conditions { get; set; }
}
// OptimizelyEvent is a class describing an event and inherited from Entity.IdKeyEntity.
public class OptimizelyEvent : Entity.IdKeyEntity
{
public string[] ExperimentIds { get; set; }
}
// OptimizelyFeature is a class describing a feature flag and inherited from Entity.IdKeyEntity.
public class OptimizelyFeature : Entity.IdKeyEntity
{
public List<OptimizelyExperiment> ExperimentRules { get; private set; }
public List<OptimizelyExperiment> DeliveryRules { get; private set; }
public IDictionary<string, OptimizelyVariable> VariablesMap { get; private set; }
[Obsolete("Use experimentRules and deliveryRules.")]
public IDictionary<string, OptimizelyExperiment> ExperimentsMap { get; private set; }
}
// OptimizelyExperiment is a class describing an experiment and inherited from Entity.IdKeyEntity.
public class OptimizelyExperiment : Entity.IdKeyEntity
{
public IDictionary<string, OptimizelyVariation> VariationsMap { get; private set; }
public string Audiences { get; private set; }
}
// OptimizelyVariation is a class describing a variation in an experiment and inherited from Entity.IdKeyEntity.
public class OptimizelyVariation : Entity.IdKeyEntity
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public bool? FeatureEnabled { get; private set; }
public IDictionary<string, OptimizelyVariable> VariablesMap { get; private set; }
}
// OptimizelyVariable is a class describing a feature flag variable and inherited from Entity.IdKeyEntity.
public class OptimizelyVariable : Entity.IdKeyEntity
{
public string Type { get; private set; }
public string Value { get; private set; }
}
Examples
OptimizelyConfig can be accessed from OptimizelyClient (top-level) like this:
var optimizelyConfig = optimizely.GetOptimizelyConfig();
// Get the revision
Console.WriteLine($"[OptimizelyConfig] revision:{optimizelyConfig.Revision}");
// Get the SDK key
Console.WriteLine($"[OptimizelyConfig] SDKKey:{optimizelyConfig.SDKKey}");
// Get the environment key
Console.WriteLine($"[OptimizelyConfig] environmentKey:{optimizelyConfig.EnvironmentKey}");
// All attributes
Console.WriteLine("[OptimizelyConfig] attributes:");
var attributes = optimizelyConfig.Attributes;
foreach (var attribute in attributes)
{
Console.WriteLine(
$"[OptimizelyAttribute] -- (id, key) = (({attribute.id}), ({attribute.key}))");
}
// All audiences
Console.WriteLine("[OptimizelyConfig] audiences:");
var audiences = optimizelyConfig.Audiences;
foreach (var audience in audiences)
{
Console.WriteLine(
$"[OptimizelyAudience] -- (id, name, conditions) = (({audience.Id}), ({audience.Name}), ({audience.Conditions}))");
// use audience data here.
}
// All events
Console.WriteLine("[OptimizelyConfig] events:");
var events = optimizelyConfig.Events;
foreach (var _event in events)
{
Console.WriteLine(
$"[OptimizelyEvent] -- (id, key, experimentIds) = (({_event.Id}), ({_event.Key}), ({_event.ExperimentIds}))");
// use event data here.
}
// All flags
var flags = optimizelyConfig.FeaturesMap.Values;
foreach (var flag in flags)
{
// use experiment rules and delivery rules and other flag data here...
var experimentRules = flag.ExperimentRules;
foreach (var experimentRule in experimentRules)
{
Console.WriteLine($"[OptimizelyExperiment] - experiment rule-key = {experimentRule.Key}");
Console.WriteLine(
$"[OptimizelyExperiment] - experiment audiences = {experimentRule.Audiences}");
// all variations
var variations = experimentRule.VariationsMap.Values;
foreach (var variation in variations)
{
Console.WriteLine(
$"[OptimizelyVariation] -- variation = {{ key: {variation.Key}, id: {variation.Id}, featureEnabled: {variation.FeatureEnabled} }}");
var variables = variation.VariablesMap.Values;
foreach (var variable in variables)
{
Console.WriteLine(
$"[OptimizelyVariable] --- variable: {variable.Key}, {variable}");
// use variable data here.
}
// use experimentRule data here.
}
var deliveryRules = flag.DeliveryRules;
foreach (var deliveryRule in deliveryRules)
{
Console.WriteLine($"[OptimizelyExperiment] - delivery rule-key = {deliveryRule.Key}");
Console.WriteLine(
$"[OptimizelyExperiment] - delivery audiences = {deliveryRule.Audiences}");
// use delivery rule data here.
}
}
// Listen to OPTIMIZELY_CONFIG_UPDATE to get updated data
NotificationCenter.OptimizelyConfigUpdateCallback configUpdateListener = () =>
{
var config = optimizely.GetOptimizelyConfig();
Console.WriteLine($"[OptimizelyConfig] revision = {config?.revision}");
};
optimizely.NotificationCenter.AddNotification(
NotificationCenter.NotificationType.OptimizelyConfigUpdate, configUpdateListener);
}
Updated about 1 year ago