/// <summary>
        /// Evaluates a feature flag for a given user.
        /// </summary>
        /// <param name="flag">the flag; must not be null</param>
        /// <param name="user">the user</param>
        /// <param name="eventFactory">an <see cref="EventFactory"/> instance that will be called to produce any necessary
        /// prerequisite flag events</param>
        /// <returns>an <see cref="EvalResult"/> containing the evaluation result as well as any events that were produced;
        /// the PrerequisiteEvents list will always be non-null</returns>
        public EvalResult Evaluate(FeatureFlag flag, User user, EventFactory eventFactory)
        {
            if (flag.Key == FlagKeyToTriggerErrorForTesting)
            {
                throw new Exception(ErrorMessageForTesting);
            }
            if (user == null || user.Key == null)
            {
                _logger.Warn("User or user key is null when evaluating flag: {0} returning null",
                             flag.Key);

                return(new EvalResult(
                           new EvaluationDetail <LdValue>(LdValue.Null, null, EvaluationReason.ErrorReason(EvaluationErrorKind.UserNotSpecified)),
                           ImmutableList.Create <EvaluationEvent>()));
            }

            var scope = new EvalScope(this, flag, user, eventFactory);

            return(scope.Evaluate());
        }
 // Checks prerequisites if any; returns null if successful, or an EvaluationReason if we have to
 // short-circuit due to a prerequisite failure. May add events to _prereqEvents.
 private EvaluationReason?CheckPrerequisites()
 {
     foreach (var prereq in _flag.Prerequisites)
     {
         var prereqOk          = true;
         var prereqFeatureFlag = _parent._featureFlagGetter(prereq.Key);
         if (prereqFeatureFlag == null)
         {
             _parent._logger.Error("Could not retrieve prerequisite flag \"{0}\" when evaluating \"{1}\"",
                                   prereq.Key, _flag.Key);
             prereqOk = false;
         }
         else
         {
             var prereqScope      = new EvalScope(_parent, prereqFeatureFlag, _user, _eventFactory);
             var prereqEvalResult = prereqScope.Evaluate();
             var prereqDetails    = prereqEvalResult.Result;
             // Note that if the prerequisite flag is off, we don't consider it a match no matter
             // what its off variation was. But we still need to evaluate it in order to generate
             // an event.
             if (!prereqFeatureFlag.On || prereqDetails.VariationIndex == null || prereqDetails.VariationIndex.Value != prereq.Variation)
             {
                 prereqOk = false;
             }
             foreach (var subPrereqEvent in prereqEvalResult.PrerequisiteEvents)
             {
                 _prereqEvents.Add(subPrereqEvent);
             }
             _prereqEvents.Add(_eventFactory.NewPrerequisiteEvaluationEvent(prereqFeatureFlag, _user,
                                                                            prereqDetails, _flag));
         }
         if (!prereqOk)
         {
             return(EvaluationReason.PrerequisiteFailedReason(prereq.Key));
         }
     }
     return(null);
 }