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

Question: Can you get matching results back? #13

Open
mdegroot71 opened this issue Oct 13, 2019 · 7 comments
Open

Question: Can you get matching results back? #13

mdegroot71 opened this issue Oct 13, 2019 · 7 comments

Comments

@mdegroot71
Copy link

First off, let me say that this is an excellent project! I have been able to do more in solving my business problem with your code than any other rules engine that I've researched and/or worked with!

I have a situation where I need to select groups of objects from a collection. For example, if I have a collection of programs of type TANF, SNAP and MED, in a collection, with your code, I've been able to create a rule that will evaluate true if the collection has all three or TANF & SNAP only or TANF & MED only or just TANF alone and false if TANF isn't included. This is exactly what I want with the rule. Yeah! While I am able to determine if collection elements satisfy the condition, currently I am unable to determine which elements were matched. What if I defined a rule that said "IF [TANF and SNAP or MED or TANF] or [LTC and SNAP or MED or LTC]", I would need to know if TANF matched or if LTC matched.

What I would like to do, is execute the expression against the collection, determine if the rule is satisfied AND be able to execute the rule to return back the matching results. Predicates and LINQ expression trees are new to me so I'm not sure if this is possible or not. What do you think? Is it possible?

Thanks,

Michael

@runxc1
Copy link
Owner

runxc1 commented Oct 13, 2019

So I just checked in a few changes that should help you out. The MRE creates an Expression Tree but was only exposing a compiled Func. I added a new method that exposes the Expression and allows you to use it against any Linq Provider. Check out the code in this test class https://github.com/runxc1/MicroRuleEngine/blob/master/MicroRuleEngine.Core.Tests/ExpressionToSQLQueryTest.cs

@mdegroot71
Copy link
Author

mdegroot71 commented Oct 13, 2019

Thank you for the swift response. Wow! Thank you for exposing the expression.

One problem I have, I think, is how I've crafted my rule. Here's an example of a rule that I've created:


             var RuleObject = new Rule
                {
                    Operator = ExpressionType.AndAlso.ToString("g"),
                    Rules = new List<Rule>
                    {
                    new Rule { MemberName = "Programs", Operator = "Any", Rules = new [] { new Rule { MemberName = "Name", Operator = "Equal", TargetValue="TANF"} } },
                    new Rule
                    {
                        Operator = "Or",
                        Rules = new List<Rule>
                        {
                            new Rule { MemberName = "Programs", Operator = "Any", Rules = new [] { new Rule { MemberName = "Name", Operator = "Equal", TargetValue = "SNAP"} } },
                            new Rule { MemberName = "Programs", Operator = "Any", Rules = new [] { new Rule { MemberName = "Name", Operator = "Equal", TargetValue = "MED" } } },
                            new Rule { MemberName = "Programs", Operator = "Any", Rules = new [] { new Rule { MemberName = "Name", Operator = "Equal", TargetValue = "TANF" } } }
                        }
                    }
                }
                }

As you can see, I am passing the parent object into the rule as an argument and the rules operate against the collection contained therein. If my collection has an entry for TANF alone, or TANF and SNAP or TANF and MED or all three, it will return true. It works surprisingly.

Can you think of anyway I can evaluate this rule to get back the rows?

Thanks,

Michael

@runxc1
Copy link
Owner

runxc1 commented Oct 13, 2019

I can't quite say that I follow 100% but I don't see any reason you couldn't get an Expression from that and use it against your collection. Are you trying to do something like the following.

public List<SomeType> GetMatching(List<SomeType> AllTheThings)
{
 var rule = GetMyRule();
 var expression = MRE.ToExpression<SomeType>(rule);
 var toReturn = AllTheThings.Where(expression).ToList();
 return toReturn;
}

@mdegroot71
Copy link
Author

mdegroot71 commented Oct 13, 2019

Thank you for your response! When I execute the rule, I execute it passing in the parent object, Selection. A Selection object has a collection of Program objects. Each Program object has a Name property. If I go like this...
`var expression = MRE.ToExpression(rule);

selection.Programs.Where(expression).ToList();
`
it will say that it cannot find the property Programs on the Program object. This is because the rule operates at the Selection object level so that it can use Any multiple times on the child collection.

Is there some way that I can execute the expression against the Selection object and get the child objects back? I've used basic LINQ before but this expression tree stuff is very new to me.

Thanks,

Michael

@mdegroot71
Copy link
Author

Thank you for your help! I found the answer. I took my Selection object and put it in a list. I then executed a .Where() on that list which then evaluated the child objects and returns them. Thank you for adding that ToExpression method!

@mdegroot71
Copy link
Author

Sorry, I spoke too soon. Here's the code I wrote...

` var expression = MRE.ToExpression(rule.RuleObject);
List selections = new List { selection };
var selectionProgramsMatched = selections.AsQueryable().Where(expression).ToList();

`
What happens is the sole Selection object matches the rule and thus the object is returned as-is with all Programs included. There is no filtering of the program objects. We are very close I feel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
@runxc1 @mdegroot71 and others