Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize when rules cascade based on input properties #3616

Closed
rockfordlhotka opened this issue Dec 19, 2023 Discussed in #3415 · 0 comments · Fixed by #3618
Closed

Optimize when rules cascade based on input properties #3616

rockfordlhotka opened this issue Dec 19, 2023 Discussed in #3415 · 0 comments · Fixed by #3618

Comments

@rockfordlhotka
Copy link
Member

Discussed in #3415

Originally posted by mtavares628 August 1, 2023
I've noticed this issue which ends up causing the same rules on my object to be run over and over. Basically if I pass properties (besides the PrimaryProperty) to the constructor of my rule (Rule A), and that passed in property is used as a PrimaryProperty in some other rule (Rule B), then Rule A gets called again whenever Rule B has been called. I would expect this to happen if I added the property to the AffectedProperties list for the rule, or added a Dependency rule between the 2 properties, but I'm not doing that.

Here is a sample that recreates the behavior. If you set a breakpoint on ExecuteAsync of the IDRule below, then it will get called twice when CheckRules is called.

[Serializable]
    public class Root : BusinessBase<Root>
    {
        public static readonly PropertyInfo<string> NameProperty = RegisterProperty<string>(nameof(Name));
        public string Name
        {
            get => GetProperty(NameProperty);
            set => SetProperty(NameProperty, value);
        }

        public static readonly PropertyInfo<Csla.SmartDate> ReferenceDateProperty = RegisterProperty<Csla.SmartDate>(nameof(ReferenceDate));

        public string ReferenceDate
        {
            get => GetPropertyConvert<Csla.SmartDate, string>(ReferenceDateProperty);
            set => SetPropertyConvert<Csla.SmartDate, string>(ReferenceDateProperty, value);
        }

        public static readonly PropertyInfo<int> IDProperty = RegisterProperty<int>(nameof(ID));

        public int ID
        {
            get => GetProperty(IDProperty);
            set => SetProperty(IDProperty, value);
        }
        


        protected override void AddBusinessRules()
        {
            base.AddBusinessRules();
            BusinessRules.AddRule(new ReferenceDateRule(ReferenceDateProperty));
            BusinessRules.AddRule(new IDRule(IDProperty, ReferenceDateProperty));

            //BusinessRules.AddRule(new MyRule { PrimaryProperty = NameProperty });
        }

        [Fetch]
        private void Fetch() 
        {
            using (BypassPropertyChecks)
            {
                Name = "Test";
                ReferenceDate = DateTime.Today.ToShortDateString();
                ID = 1;
            }
            BusinessRules.CheckRules();
        }
    }

public class ReferenceDateRule : Csla.Rules.BusinessRuleAsync
    {
        //IPropertyInfo IDProperty;

        public ReferenceDateRule(IPropertyInfo primaryProp) : base(primaryProp)
        {
            InputProperties = new List<IPropertyInfo>() { PrimaryProperty };

        }

        protected override async Task ExecuteAsync(IRuleContext context)
        {
            // breakpoint vvv
            context.AddSuccessResult(false);
        }
    }

    public class IDRule : Csla.Rules.BusinessRuleAsync
    {
        IPropertyInfo ReferenceDateProperty;

        public IDRule(IPropertyInfo primaryProp, IPropertyInfo referenceDateProp) : base(primaryProp)
        {
            ReferenceDateProperty = referenceDateProp;

            InputProperties = new List<IPropertyInfo>() { PrimaryProperty, ReferenceDateProperty };

        }

        protected override async Task ExecuteAsync(IRuleContext context)
        {
            // breakpoint vvv
            context.AddSuccessResult(false);
        }
    }

Is this by design? And if so, then how can I create rules with multiple properties, and prevent the rule from being called multiple times if the secondary (non-PrimaryProperty) has it's own set of rules? I can't use the Target object either, since my rules need to be Async for Blazor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging a pull request may close this issue.

1 participant