Rule with multiple properties only fires when the Primary Property changes #3720
Replies: 6 comments 52 replies
-
Extra parameters on the rule's constructor need to be added to the InputProperties collection. The GitHub repo has a RuleTutorial project with some examples that contain multiple properties. A good example is GreaterThanOrEqual. Here's the constructor from that sample:
Note that the primary property and the comparison property are both added to the InputProperties collection. A SetProperty call to either property will cause the rule to be executed. |
Beta Was this translation helpful? Give feedback.
-
Here's my unit test:
|
Beta Was this translation helpful? Give feedback.
-
I have several csla 4.xx applications. My observation is the same as what @lwmorris067 described. |
Beta Was this translation helpful? Give feedback.
-
To my understanding the AffectedProperties list is used to fire the rules for the property that you add to the list where that property is the primary property, not fire the rule that you are in when that affected property changes. The same thing is actually true of the InputProperties as well. It would fire off the rules for all of the other input properties where those properties have rules where they are the primary property. With the old logic, depending upon what your other rules would look like, you could end up in a situation where the Affected/InputProperties would trigger the original rule as a dependency from ping-ponging back and forth between the rules. With the change, the InputProperties's rules are only fired if those input property values actually changed. Otherwise, they don't fire. The only real way to guarantee that your rule triggers from the dependency is to use the Dependency rule like you did. @rockfordlhotka That was why I was proposing creating a TriggeredProperties list in the rule that would have the rule run whenever one of the properties in that list were changed, and it would encapsulate all of the dependencies within the rule. Here's what I was proposing: #3415 (reply in thread) |
Beta Was this translation helpful? Give feedback.
-
I am enjoying this discussion, I need to allocate some time to this over the weekend. |
Beta Was this translation helpful? Give feedback.
-
I'd like to reset the discussion a bit, as I want to more clearly understand the desired behavior. Right now in the CSLA 8 preview, For example, this is some output (code is below):
The first block is from The second block is due to a change to the date property - so only the date rule runs. The third block is due to a change to the ID property - and From this code: using Csla;
using Csla.Configuration;
using Csla.Core;
using Csla.Rules;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddCsla();
var provider = services.BuildServiceProvider();
var portal = provider.GetRequiredService<IDataPortal<Root>>();
var obj = portal.Fetch();
Console.WriteLine("---");
obj.ReferenceDate = "tom";
Console.WriteLine("---");
obj.ID = 2;
[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
{
public ReferenceDateRule(IPropertyInfo primaryProp) : base(primaryProp)
{
InputProperties = new List<IPropertyInfo>() { PrimaryProperty };
}
protected override async Task ExecuteAsync(IRuleContext context)
{
context.AddSuccessResult(false);
Console.WriteLine(nameof(ReferenceDateRule));
}
}
public class IDRule : Csla.Rules.BusinessRuleAsync
{
IPropertyInfo ReferenceDateProperty;
public IDRule(IPropertyInfo primaryProp, IPropertyInfo referenceDateProp) : base(primaryProp)
{
ReferenceDateProperty = referenceDateProp;
InputProperties = new List<IPropertyInfo>() { PrimaryProperty, ReferenceDateProperty };
AffectedProperties.Add(referenceDateProp);
}
protected override async Task ExecuteAsync(IRuleContext context)
{
context.AddSuccessResult(false);
Console.WriteLine(nameof(IDRule));
}
} |
Beta Was this translation helpful? Give feedback.
-
I have a rule that takes multiple properties to calculate something. I thought that CSLA automatically associated all the properties passed in the constructor so that any changes to any of the properties would cause the rule to execute. It fires when the PrimaryProperty changes, but none of the properties added to the InputProperties or AffectedProperties collection.
I'm either remembering incorrectly or that's not the way the v8 pre-release (8.0.0-R24021201) works, or I'm just doing something wrong. I have not utilized the Dependency rule.
"CSLA .NET provides a rule designed specifically to set up dependency relationships between
properties. In many cases, dependencies are automatically detected because properties affected by
a rule become dependent properties. But sometimes you’ll want to explicitly designate a
dependency relationship by using the Dependency rule."
Beta Was this translation helpful? Give feedback.
All reactions