Calculating Rules for two Dependend Properties

Calculating Rules for two Dependend Properties

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


tsvideo posted on Thursday, April 25, 2013

CSLA Version 4.1

Hello !

I have two Properties: one called DeliveryWeek (LieferKW) and one called DeliveryDate (Liefertermin).
Further i have two Rules which calculate a DeliveryDate (Friday of Week) from DeliveryWeek
and one Rule that calculate a DeliveryWeek vom DeliveryDate.
The User must can change both (vice versa) in the WPF UI and the other Field must be updated.
The Problem is, that when the user enter a new DeliveryDate the CalculateLieferterminRule runs first
and reset the DeliveryDate.
What is the right Way to setup the Rules ?

My Code:
        protected override void AddBusinessRules()
        {
            base.AddBusinessRules();

            //Some Other Rules for Required Fields
           
            //BusinessRules.AddRule(new Csla.Rules.CommonRules.Dependency(LieferKWProperty, LieferterminProperty));
            //BusinessRules.AddRule(new Csla.Rules.CommonRules.Dependency(LieferterminProperty, LieferKWProperty));
            BusinessRules.AddRule(new CalculateLieferterminRule(LieferterminProperty, LieferKWProperty){Priority = 1});
            BusinessRules.AddRule(new CalculateLieferKWRule(LieferKWProperty, LieferterminProperty) { Priority = 1 });

        }
       
        private class CalculateLieferterminRule : BusinessRule
        {
            private IPropertyInfo LieferKWProperty;
           
            public CalculateLieferterminRule(IPropertyInfo primaryProperty, IPropertyInfo lieferKWProperty) : base(primaryProperty)
            {
                if (InputProperties == null)
                {
                    InputProperties = new List<IPropertyInfo>() {primaryProperty, lieferKWProperty};
                }

                PrimaryProperty = primaryProperty;
                LieferKWProperty = lieferKWProperty;
                AffectedProperties.Add(PrimaryProperty);

            }

            protected override void Execute(RuleContext context)
            {
                var lieferKw = Convert.ToInt32(context.InputPropertyValues[LieferKWProperty]);
                DateTime? liefertermin = DateTimeExtension.GetLastBusinessDateOfWeek(lieferKw);

                context.AddOutValue(PrimaryProperty, liefertermin);
            }

        }

        private class CalculateLieferKWRule : BusinessRule
        {
            private IPropertyInfo LieferterminProperty;
           
            public CalculateLieferKWRule(IPropertyInfo primaryProperty, IPropertyInfo lieferterminProperty) : base(primaryProperty)
            {
                if (InputProperties == null)
                {
                    InputProperties = new List<IPropertyInfo>() {primaryProperty, lieferterminProperty};
                }

                PrimaryProperty = primaryProperty;
                LieferterminProperty = lieferterminProperty;
                AffectedProperties.Add(PrimaryProperty);
            }

            protected override void Execute(RuleContext context)
            {
                var liefertermin = Convert.ToDateTime(context.InputPropertyValues[LieferterminProperty]);
                int lieferKW = DateTimeExtension.GetCalendarWeekWithYear(liefertermin);

                context.AddOutValue(PrimaryProperty, lieferKW);
            }
        }

 

 

JonnyBee replied on Thursday, April 25, 2013

Hi,

First. Remove the dependecy rules.  AffectedProperty creates a dependency.

Then rewrite the rules to set the "AffectedProperty" -  ie: the CalculateLieferKWRule should have LieferTerminProperty as primary property and LieferKWProperty as Output property/AffectedProperty.

The rule engine will for a given property run the rules

So as your rules is defined now - when LieferterminProperty is changed the rules where LiferterminProperty is primary property will run first and that is the CalculateLieferteminRule. 

tsvideo replied on Friday, April 26, 2013

Hello Jonny,
thank you for your quick answer, it works. I was some Kind of BlindSmile, Naturally must the Primary Property be the Property wich is the source for the calculating.

But for me i have another question with Rules.

What is the best 'CSLA Style' to implement such calculations and what is the effort to make it in Rules ?
I mean, that i also can do this sort of calculation in the setter of the Property.
In the RuleTutorial are a lot of Validation Rules, but not so many Calculation Rules.

JonnyBee replied on Friday, April 26, 2013

Hi Thilo,

In general terms:

Starting from CSLA 4.2 you can also tell the rule engine when NOT to run the rule:

You should also look at my blog posts:

http://jonnybekkum.wordpress.com/2011/08/29/csla-4-2-rules-update/
http://jonnybekkum.wordpress.com/2012/11/07/csla-4-5-ruleengine-update/

Copyright (c) Marimer LLC