Exemplo n.º 1
0
        /// <inheritdoc/>
        public virtual async ValueTask <IFact> CalculateFactAsync <TFactRule, TWantAction, TFactContainer>(NodeByFactRule <TFactRule> node, IWantActionContext <TWantAction, TFactContainer> context)
            where TFactRule : IFactRule
            where TWantAction : IWantAction
            where TFactContainer : IFactContainer
        {
            (var rule, var buildSuccessConditions, var runtimeConditions) =
                (node.Info.Rule, node.Info.BuildSuccessConditions, node.Info.RuntimeConditions);

            foreach (IRuntimeConditionFact condition in runtimeConditions)
            {
                (bool calculated, IFact result) = await TryCalculateFactByRuntimeConditionAsync(rule, condition, context);

                if (calculated)
                {
                    return(result);
                }
            }

            using (var writer = context.Container.GetWriter())
            {
                buildSuccessConditions.ForEach(writer.Add);
                runtimeConditions.ForEach(writer.Add);
            }

            var requiredFacts = GetRequireFacts(rule, context);

            if (!CanInvokeWork(requiredFacts, rule, context.Cache))
            {
                throw CommonHelper.CreateDeriveException(ErrorCode.InvalidOperation, $"Can't calculate the '{rule}' rule.", context.WantAction, context.Container);
            }

            IFact fact = await Factory
                         .CreateObject(facts => rule.CalculateAsync(facts), requiredFacts)
                         .ConfigureAwait(false);

            fact.SetCalculateByRule();
            context.WantAction.AddUsedRule(rule);

            using (var writer = context.Container.GetWriter())
            {
                buildSuccessConditions.ForEach(writer.Remove);
                runtimeConditions.ForEach(writer.Remove);
            }

            return(fact);
        }