views:

117

answers:

1

I have a method which have this signture

public static IList<T> GetBy<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression)

i use to pass lambda expressions and make search restriction in nhibernate by reteriving data from expressiontree

so when class user pass something like :

c => c.fullName == "John" && c.lastName == "Smith" && c.lastName != "" || c.fullName != ""  && c.Age > 18

i get to read this structure from expression tree , that way i have a fully intellisense way to provide searching criteria

in other words

i need to pass searching criteria to data access layer(Nhibernate)

so i need to extract criteria from expression tree and then pass it to n hibernate by example :

c=>c.fullname = "John" 

i will extract the following information from the expression tree :

propertyname = fullname , value = "John" , restrictiontype = "equality" and then pass this info to nhibernate as following :

ICriteria crit = session.CreateCriteria(typeof(T));
                    crit.Add(Restrictions.Eq(propretyName, value));
    IList<T> list = crit.Add(List<T>())
                    return list;

any way the problem is its really hard to read from expressiontree ,so i was wondering if you guys have any easy way of maybe iterating inside expressiontree to pull data, or maybe you guys have some code to reterive data from ExpressionTree.

hope that made it more clear

thanks in advance

+2  A: 

Here is some code that retrieves the information you mentioned. I’m sure you can extend this to include additional information you might be looking for.

public class Criterion
{
    public string PropertyName;
    public object Value;
    public ExpressionType RestrictionType;
}

[....]

public static IEnumerable<Criterion> GetCriteria<T>(Expression<Func<T, bool>> expression)
{
    return getCriteria<T>(expression.Body);
}
private static IEnumerable<Criterion> getCriteria<T>(Expression expression)
{
    if (expression is BinaryExpression)
    {
        var bin = (BinaryExpression) expression;
        if (bin.NodeType == ExpressionType.And || bin.NodeType == ExpressionType.AndAlso ||
            bin.NodeType == ExpressionType.Or || bin.NodeType == ExpressionType.OrElse)
            return getCriteria<T>(bin.Left).Concat(getCriteria<T>(bin.Right));

        if (bin.Left is MemberExpression)
        {
            var me = (MemberExpression) bin.Left;
            if (!(bin.Right is ConstantExpression))
                throw new InvalidOperationException("Constant expected in criterion: " + bin.ToString());
            return new[] { new Criterion {
                PropertyName = me.Member.Name,
                Value = ((ConstantExpression) bin.Right).Value,
                RestrictionType = bin.NodeType
            } };
        }

        throw new InvalidOperationException("Unsupported binary operator: " + bin.NodeType);
    }

    throw new InvalidOperationException("Unsupported expression type: " + expression.GetType().Name);
}
Timwi
very nice buddy i made a method like it but it always gave me exception , thanks Timwi
Stacker