Business Rule Chaining & context.AddOutValue()

Business Rule Chaining & context.AddOutValue()

Old forum URL: forums.lhotka.net/forums/t/10393.aspx


Peran posted on Monday, May 23, 2011

I have a 'selector' type business rule which chooses which one of 2 inner rules to run dependant on the object state.

 

The inner rules change the values of multiple properties in the Execute Method e.g.

            context.AddOutValue(this.Amount1Property, newAmount1);

            context.AddOutValue(this.Amount2Property, newAmount2);

            context.AddOutValue(this.Amount3Property, newAmount3);

The problem is the new values set in the inner rule do not get applied to the business object; I'm not sure if I am trying to do something that is not possible or if my implementation is wrong?
The inner rules I am using work fine if they are not part of a chain.  I have also tried ensuring the 'selector' rule AffectedProperties contains all the AffectedProperties of the inner rules, but this made no difference.
Cheers
Peran

JonnyBee replied on Monday, May 23, 2011

Workaround now  - your inner rule must call

context.Complete();

after it has set the output value or your selector rule must call Complete on the chained context. 

OutputPropertyValues is not propagated down into chained RuleContext so your code must call complete in the innermost context.

This may be regarded as a bug - but for optimized memory consumption the OuputPropertyValues dictionary is not created until the first AddOutvalue is called and so the dictionary is not passed on to chained contexts. 

If we change the GetChainedContext to

    public RuleContext GetChainedContext(IBusinessRule rule)
    {
      if (OutputPropertyValues == null)
        OutputPropertyValues = new Dictionary<Core.IPropertyInfo, object>();

      var result = new RuleContext(_completeHandler);
      result.Rule = rule;
      if (!rule.IsAsync || rule.ProvideTargetWhenAsync)
        result.Target = Target;
      result.InputPropertyValues = InputPropertyValues;
      result.OutputPropertyValues = OutputPropertyValues;
      result.Results = Results;
      return result;
    }

The rules will work as expected out of the box.

Peran replied on Monday, May 23, 2011

Thanks, calling context.Complete() on the inner most rule solved the issue.  In fact I added it to a base class of mine so it is called automatically when Execute() competes on a synchronous rule.

 

[Edit] for anyone else reading this, you also need to make sure the 'selector' rule AffectedProperties contains the inner rule AffectedProperties.

 

Peran 

Copyright (c) Marimer LLC