Note that there are some explanatory texts on larger screens.

plurals
  1. POBuilding a MicroRuleEngine using LinqExpressions
    primarykey
    data
    text
    <p>So I am building a MicroRuleEngine (Would love to see this take off as an OpenSource project) and I am running into a null reference Error When executing the compiled ExpressionTree and I am not exactly sure why. Rules against the simple properties work but going against Child Properties aka Customer.Client.Address.StreetName etc. do not work.</p> <p>Below is the MicroRuleEngine</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Linq.Expressions; namespace Trial { public class MicroRuleEngine { public bool PassesRules&lt;T&gt;(List&lt;Rule&gt; rules, T toInspect) { bool pass = true; foreach (var rule in rules) { var cr = this.CompileRule&lt;T&gt;(rule); pass = pass &amp;&amp; cr.Invoke(toInspect); if (!pass) return pass; } return pass; } public Func&lt;T, bool&gt; CompileRule&lt;T&gt;(Rule r) { var paramUser = Expression.Parameter(typeof(T)); Expression expr = BuildExpr&lt;T&gt;(r, paramUser); // build a lambda function User-&gt;bool and compile it return Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;(expr, paramUser).Compile(); } Expression BuildExpr&lt;T&gt;(Rule r, ParameterExpression param) { Expression propExpression; Type propType;// typeof(T).GetProperty(r.MemberName).PropertyType; ExpressionType tBinary; if (r.MemberName.Contains('.')) { // support to be sorted on child fields. String[] childProperties = r.MemberName.Split('.'); var property = typeof(T).GetProperty(childProperties[0]); var paramExp = Expression.Parameter(typeof(T), "SomeObject"); propExpression = Expression.MakeMemberAccess(paramExp, property); for (int i = 1; i &lt; childProperties.Length; i++) { property = property.PropertyType.GetProperty(childProperties[i]); propExpression = Expression.MakeMemberAccess(propExpression, property); } propType = propExpression.Type; propExpression = Expression.Block(new[] { paramExp }, new[]{ propExpression }); } else { propExpression = MemberExpression.Property(param, r.MemberName); propType = propExpression.Type; } // is the operator a known .NET operator? if (ExpressionType.TryParse(r.Operator, out tBinary)) { var right = Expression.Constant(Convert.ChangeType(r.TargetValue, propType)); // use a binary operation, e.g. 'Equal' -&gt; 'u.Age == 15' return Expression.MakeBinary(tBinary, propExpression, right); } else { var method = propType.GetMethod(r.Operator); var tParam = method.GetParameters()[0].ParameterType; var right = Expression.Constant(Convert.ChangeType(r.TargetValue, tParam)); // use a method call, e.g. 'Contains' -&gt; 'u.Tags.Contains(some_tag)' return Expression.Call(propExpression, method, right); } } } public class Rule { public string MemberName { get; set; } public string Operator { get; set; } public string TargetValue { get; set; } } } </code></pre> <p>And This is the Test that is Failing</p> <pre><code>[TestMethod] public void ChildPropertyRuleTest() { Container container = new Container() { Repository = "TestRepo", Shipment = new Shipment() { OrderNumber = "555" } }; MicroRuleEngine mr = new MicroRuleEngine(); var rules = new List&lt;Rule&gt;() { new Rule() { MemberName = "Shipment.OrderNumber", Operator = "Contains", TargetValue = "55" } }; var pases = mr.PassesRules&lt;Container&gt;(rules, container); Assert.IsTrue(!pases); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload