BusinessRules.GetAllBrokenRules problem with warnings

BusinessRules.GetAllBrokenRules problem with warnings

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


Smith866 posted on Tuesday, July 19, 2011

Hi,
We are having a problem using the BusinessRules.GetAllBrokenRules(obj) Method when our object graph only contains warnings in the BrokenRules collections.

This is because the AddNodeToBrukenRules recursive function checks IsValid on each BusinessBase or IEditableCollection. Only errors will propagate IsValid=false property up to an object's parents. However, the BrokenRules collection contains Errors, Warnings and Info messages. This means that we will retrieve warnings and info messages only if there are associated error messages. If there aren't any error messages, then we don't get anything at all.

What are our options to retrieve all of the warnings in an entire object graph if there are no errors? We tried to write our own implementation of GetAllBrokenRules, but we are unable to do so as the IManageProperties interface is not accessible to us (it's marked as internal), and we need IManageProperties to access GetChildren(). Is there another way to access the list of children from a BusinessBase object?

JonnyBee replied on Wednesday, July 20, 2011

Hi,

The first GetAllBroken rules would check if object was valid or not. Unfortunately this would miss objects with only warning or info.

I have a never version at work that will also accept a bool parameter to include all error levels. I can post the updated code later today.
It is not in CSLA Trunk (yet).

 

JonnyBee replied on Wednesday, July 20, 2011

Hi,

Try this code, when used with errorLevelOnly set to false you will get all objects with broken rules on any level. :

    #region Get All Broken Rules (tree)
 
    /// <summary>
    /// Gets all broken rules with Error level in object graph.
    /// </summary>
    /// <param name="root">The root.</param>
    /// <returns>BrukenRulesTree list</returns>
    public static BrokenRulesTree GetAllBrokenRules(object root)
    {
        return GetAllBrokenRules(root, true);
    }
    /// <summary>
    /// Gets all broken rules.
    /// </summary>
    /// <param name="root">The root.</param>
    /// <returns></returns>
    public static BrokenRulesTree GetAllBrokenRules(object root, bool errorsOnly)
    {
        var list = new BrokenRulesTree();
        long counter = 1;
        long childBrokenRuleCount = 0;
        AddNodeToBrukenRules(ref list, ref counter, null, root, errorsOnly, ref childBrokenRuleCount);
 
        return list;
    }
 
    private static void AddNodeToBrukenRules(ref BrokenRulesTree list, ref long counter, object parentKey, object obj, bool errorsOnly, ref long childBrokenRuleCount)
    {
        // is this a single editable object 
        if (obj is Csla.Core.BusinessBase)
        {
            var nodeKey = counter++;
            var bo = (Csla.Core.BusinessBase)obj;
            long myChildBrokenRuleCount = bo.BrokenRulesCollection.Count;
            var node = new BrokenRulesNode() { Parent = parentKey, Node = nodeKey, BrokenRules = bo.BrokenRulesCollection, Object = obj };
            list.Add(node);
 
            // get managed child properties 
            foreach (var child in ((IManageProperties)bo).GetChildren())
            {
                AddNodeToBrukenRules(ref list, ref counter, nodeKey, child, errorsOnly, ref myChildBrokenRuleCount);
            }
 
            // remove node if it has no child with broken rules. 
            if (!errorsOnly && myChildBrokenRuleCount == 0)
            {
                list.Remove(node);
            }
            if (errorsOnly && bo.IsValid)
            {
                list.Remove(node);
            }
            childBrokenRuleCount += myChildBrokenRuleCount;
        }
 
        // or a list of EditableObject (both BindingList and ObservableCollection)
        else if (obj is IEditableCollection)
        {
            var nodeKey = counter++;
            var isValid = ((ITrackStatus)obj).IsValid;
            var node = new BrokenRulesNode() { Parent = parentKey, Node = nodeKey, Object = obj };
            long myChildBrokenRuleCount = 0;
 
            list.Add(node);
 
            foreach (var child in (IEnumerable)obj)
            {
                AddNodeToBrukenRules(ref list, ref counter, nodeKey, child, errorsOnly, ref myChildBrokenRuleCount);
            }
 
            // remove node if it has no child with broken rules. 
            if (!errorsOnly && myChildBrokenRuleCount == 0)
            {
                list.Remove(node);
            }
            if (errorsOnly && isValid)
            {
                list.Remove(node);
            }
            childBrokenRuleCount += myChildBrokenRuleCount;
        }
        return;
    }
 
    #endregion

Smith866 replied on Wednesday, July 20, 2011

Works great, thanks!

Hope to see this in a future version of CSLA.

Copyright (c) Marimer LLC