|
|
Comments and Discussions
|
|
 |

|
Hi, PredicateParser fails when analyzing strings on both sides,
like "data > \"13-12-2012 10:48:00:345\"", data is string attribute too.
Does someone has a clue how it can be solved?
thanks!
|
|
|
|

|
What exactly is the problem? What do you mean by "fails"?
Can you please give a code example so that I can debug?
Thanks
Andi
PS: The predicate parser is not robust in the sense that if the property does not exist or if the type is not matching, it throws an exception.
E.g. I get a stackdump if the property does not exist (e.g. data instead of Data, etc.), or if the type of the property/value types do not match.
PPS: I can not reach you by mail (delivery refused). So, please post the coversation here. What I need to see is your Element class. My suspicion is that the Element class does not contain a data property with a public getter.
|
|
|
|

|
Hi Andreas, thanks for the response!
I'm out of the office now, you can contact-me:
ricardo.solutiontech@hotmail.com
My class is:
public class Element
{
public string Name;
public double Number;
public string data;
public Element(string a, double b,string c)
{
Name = a;
Number = b;
data = c;
}
}
public class Program
{
static void Main(string[] args)
{
var items = new List<Element>()
{
new Element("a", 1000 ,"13-12-2012 10:47:00:000"),
new Element("b", 900 ,"13-12-2012 10:48:00:345"),
new Element("b", 800 ,"13-12-2012 10:48:00:545"),
new Element("d", 700 ,"13-12-2012 11:48:00:545"),
new Element("e", 600 ,"13-12-2012 12:48:00:545"),
new Element("x", 500.5 ,"13-12-2012 14:48:00:545"),
new Element("y", 400 ,"13-12-2012 15:48:00:545"),
new Element("z", 300 ,"13-12-2012 16:48:00:545"),
};
string s = "data > \"13-12-2012 10:48:00:345\"";
Console.WriteLine("User Entry: {0}", s);
var pred = SimpleExpression.PredicateParser<Element>.Parse(s);
Console.WriteLine("Expr Tree: {0}", pred.ToString());
var f = pred.Compile();
Console.WriteLine("### mark affectd items ###");
foreach (var item in items)
{
Console.WriteLine("{2} Name = {0}, Number = {1}", item.Name, item.Number, f(item) ? "x" : " ");
}
Console.WriteLine("### where-select ###");
var q = from e in items where f(e) select e;
foreach (var item in q)
{
Console.WriteLine(" Name = {0}, Number = {1}", item.Name, item.Number);
}
System.Console.ReadKey();
}
}
|
|
|
|

|
The problem is that the C# string type does not provide any relation operator (<, <=, >=, >).
If you need string relation comparison, you need to invest into that
- translate the relation operators to the respective CompareTo(...).
- provide function support in the parser
Cheers
Andi
|
|
|
|

|
Yes Andreas, I´m working on Compare or CompareTo method, but my problem now is translate it to an expression that be compatible with the expression generated by parser when other types are used, like numbers.
Thanks for help!
|
|
|
|

|
Ok, I found a solution that I like more than introducing function support: call CompareTo instead of the implicit comparison operator.
Adjust the code as follows:
- insert before line 59:
private static readonly Expression _zero = Expression.Constant(0);
- add the following function, e.g. after line 79:
private static Expression CompareToExpression(Expression lhs, Expression rhs, Func<Expression, Expression> rel)
{
lhs = Coerce(lhs, rhs);
rhs = Coerce(rhs, lhs);
Expression cmp = Expression.Call(
lhs,
lhs.Type.GetMethod("CompareTo", new Type[] { rhs.Type })
?? lhs.Type.GetMethod("CompareTo", new Type[] { typeof(object) }),
rhs);
return rel(cmp);
}
- replace lines 88-93 by the following code:
{ "==", (a,b)=>CompareToExpression(a, b, c=>Expression.Equal (c, _zero)) },
{ "!=", (a,b)=>CompareToExpression(a, b, c=>Expression.NotEqual (c, _zero)) },
{ "<", (a,b)=>CompareToExpression(a, b, c=>Expression.LessThan (c, _zero)) },
{ "<=", (a,b)=>CompareToExpression(a, b, c=>Expression.LessThanOrEqual (c, _zero)) },
{ ">=", (a,b)=>CompareToExpression(a, b, c=>Expression.GreaterThanOrEqual(c, _zero)) },
{ ">", (a,b)=>CompareToExpression(a, b, c=>Expression.GreaterThan (c, _zero)) },
That works now with all types that implement IComparable<T>.
Cheers
Andi
PS: I've updated the tip. Please note that the sample download code only implements the basic functionality and all the extension are only mentioned in the text.
modified 5 days ago.
|
|
|
|
|

|
You are welcome!
Cheers
Andi
|
|
|
|
|
|

|
Hello Clifford,
thanks for your 5!
Andi
|
|
|
|

|
It is written in very condensed logic which covers a lot of parsing and cleverly uses regular expression to scan tokens. While complex statements need advanced scanner with character basis scanning, your technique simplified a lot of works needed for simple statements. There is only one typo error found at line 107, _para should be _param.
|
|
|
|

|
Hello Matthew,
Thanks for your 5!
I've updated the tip: fixed the typo, added the sources to download. See the version text.
Cheers
Andi
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
This is an alternative for "Dynamically generate a LINQ query with a custom property".
| Type | Tip/Trick |
| Licence | MIT |
| First Posted | 27 Mar 2012 |
| Views | 12,447 |
| Downloads | 158 |
| Bookmarked | 30 times |
|
|