It is continuation of first post - << click here to read
and second post - < click here to read
Dynamicity is of great advantage. First of all let us move forward step wise, define delegate to a separate method;
and second post - < click here to read
Dynamicity is of great advantage. First of all let us move forward step wise, define delegate to a separate method;
should tends to
rule.AddCondtion(IsPriceGreaterOrEqualToZero());
public static Predicate<PriceObject> IsPriceGreaterOrEqualToZero()
{
return delegate(PriceObject po) { return po.NetProductPrice >= 0; };
}
Let us consider even more generic function to write. Point is every condition returns Predicate<PriceObject> and internally the condition result is a Boolean variable (true/false). Why not create runtime generic delegate to handle Equals operator for example. We will make it compatible to other operators later.
public static Predicate<T> GetConditiPredicate<T>(string fieldName, string operatorName, string value)
{
Type itemType = typeof(T);
ParameterExpression predParam = Expression.Parameter(itemType, "po");
PropertyInfo propertyInfo = itemType.GetProperty(fieldName);
Expression left = Expression.Property(predParam, propertyInfo);
Expression right = Expression.Constant(ObjTypeConverter.ChangeType(value, propertyInfo.PropertyType), propertyInfo.PropertyType);
Expression equality = Expression.GreaterThanOrEqual(left, right);
Func<T, bool> function = (Func<T, bool>)Expression.Lambda(equality, new[] { predParam }).Compile();
return new Predicate<T>(function);
}
And caller can deliver a call like this
rule.AddCondtion(Dynamic.GetConditiPredicate<PriceObject>("DRM", "Equals", "2"));
Well compile and see if it works fine. It should :)
Now let us replace the statement with more general one….
//Expression equality = Expression.GreaterThanOrEqual(left, right);
Expression result = GetExpression(operatorName, left, right);
Func<T, bool> function = (Func<T, bool>)Expression.Lambda(result, new[] { predParam }).Compile();
And
public static Expression GetExpression(string operatorName, Expression left, Expression right)
{
Expression result = null;
switch (operatorName.ToLower())
{
case "equals":
result = Expression.Equal(left, right);
break;
case "greaterorequal":
result = Expression.GreaterThanOrEqual(left, right);
break;
case "lessorequal":
result = Expression.LessThanOrEqual(left, right);
break;
case "greaterthan":
result = Expression.GreaterThan(left, right);
break;
case "lessthan":
result = Expression.LessThan(left, right);
break;
case "add":
result = Expression.Add(left, right);
break;
case "subtract":
result = Expression.Subtract(left, right);
break;
case "multiply":
result = Expression.Multiply(left, right);
break;
case "divide":
result = Expression.Divide(left, right);
break;
default:
throw new Exception("Unknown Operator Name");
}
return result;
}
Nice Post. Thanks for sharing this.
ReplyDeleteCan I have the full sample project (source code) please?
Done; Sorry for delay. I added the link 'download from skydrive' FileName: ConfigurableRuleEngine.zip - in the bottom of this post.
Delete/Basharat
very nice job my friend.
ReplyDeleteAs Salamu Alaikum Bhai Basharat ,
ReplyDeletei am from Delhi,
i was using your code ,
and i found that it works for decimal types only
if a DateTime Parameter in priceobject is used it does not support it and it is obvious because you have used decimal types for the engine in action ....
can you give a solution for all Data types ??
JazakAllahu Khair
Hope All is good in Pakistan InshAllah !!!
And Bhai can u please give a application using mvc3 with aspx view engine ......
ReplyDeleteJazakAllahu Khair
Hi Bashrat.Nice article.but i am unable to download the file from the above link.Also what is the LogicalOperation Operation .is the custom developed class(LogicalOperation) or predefined one,please confirm
ReplyDeleteGreat & helpful article. I was trying to figure out how to define a custom action whereby it is a custom method I would like to invoke. Do you have an example of such a call?
ReplyDelete