MarimerLLC / cslaforum

Discussion forum for CSLA .NET
https://cslanet.com
Other
31 stars 6 forks source link

Pass parameter to Business Object to use in BusinessRules. #32

Open jchabot1979 opened 9 years ago

jchabot1979 commented 9 years ago

Hi. I have a Business object "DoorDetail" that has as Property "Glazing" and another property "Glass". When this GLazing property change, A rules that load the Default Glass property is executed. This rule Fetch the default Glass by GlazingID, but also needs a CustomerID and a DoorID that I have in the viewModel to Fetch the Default Glass. This viewModel is the same that has the instance of the DoorDetail. What's the best practice to solve this problem? Do I have to add a property CustomerID and DoorID to the BusinessObject and passe it from the ViewModel?? It looks weird.

Here's the code of the Rules.

private class LoadDefaultGlassOption : Csla.Rules.BusinessRule { public IPropertyInfo Glass { get; set; }

            public LoadDefaultGlassOption(IPropertyInfo glazingProperty, IPropertyInfo glassProperty)
                : base(glazingProperty)
            {
                Glass = glassProperty;
                InputProperties = new List<IPropertyInfo> { glazingProperty };
                AffectedProperties.Add(Glass);
            }

            protected override void Execute(RuleContext context)
            {
                var customerID = ?
                var door = ?
                var glazing = ((BusinessObjects.MF_Product.LightBusinessObjects.viewProductGlazing)context.InputPropertyValues[PrimaryProperty]);
                var glass = glazing != null && door != null ? BusinessObjects.MF_Product.LightBusinessObjects.viewProductGlass.GetDefaultGlass(door.ID, customerID, glazing.ProductID) : null;

                context.AddOutValue(Glass, glass);
            }
        }

Thanks a lot!!

jonnybee commented 9 years ago

My preference is to NOT use BusinessRules to load complex objects (as in Lazy Load Properties). A business rule must be considered a singelton and shared instance for ALL instances of this type. So the only way to send parameters is to pass them as properties in the BO.

You must also remember that rules may be run often - and not just when a property is changed.

There is some possibilities to limit when a rule is called, look at PropertyRule base class and the properties:

And see my blog post https://jonnybekkum.wordpress.com/2011/08/29/csla-4-2-rules-update/

You must also be aware that the PropertyChanged event is also used to notify the UI of "possible" changes in a property in order to update the displayed value.

You could also implement this in the ViewModel - that already has the CustomerID and DoorID by subscribing to the PropertyChanged on the DoorDetail object.

jonnybee commented 9 years ago

You could store values into LocalContext dictionary and have the rule read values from the context - but I would not recommend that approach.

rockfordlhotka commented 9 years ago

The business object should contain all the information necessary for it to do its work. If it needs those values, then those values should be properties (probably read-only) in the object.

I wouldn't think they'd be passed in by the viewmodel - they'd be provided as part of the criteria used to create/fetch the object.

If those values are changing during the lifetime of the object, then perhaps your object model needs to be rethought a little to recognize that there are other objects at play.