4

I have code like

DepartmentPaperConsumption dto = null;

then later i have NHibernate QueryOver result, and i want to order it

result.OrderByAlias(() => dto.TotalColorCopys);

but I want to be able to specify any property of dto dynamicly with string. I tryed using Dynamic LINQ but is seems that I just can't get it. I also tried building LambdaExpression from ground up - also without luck. I would appreciate any help.

Rami Alshareef
  • 6,554
  • 11
  • 40
  • 73
Andrej Slivko
  • 1,236
  • 1
  • 12
  • 27

3 Answers3

10

You can see how to construct the lambda here, but it really is pretty simple in your case:

var arg = Expression.Constant(null, typeof(DepartmentPaperConsumption));
var body = Expression.Convert(Expression.PropertyOrField(arg, propertyName),
    typeof(object));
var lambda = Expression.Lambda<Func<object>>(body);

The tricky thing is invoking the OrderByAlias - using MakeGenericMethod may be the way, as shown in the link above.

Community
  • 1
  • 1
Marc Gravell
  • 927,783
  • 236
  • 2,422
  • 2,784
  • That can't possibly be the Expression the OP wants. – Ani Jan 27 '11 at 12:54
  • @Ani - OK, I will fix that. Not having the signature doesn't help ;p – Marc Gravell Jan 27 '11 at 12:55
  • @Ani - any better for you now? – Marc Gravell Jan 27 '11 at 12:58
  • +1. Ah, now we are closer, but it's hard to proceed without knowing more about OrderByAlias (signature, overloads etc). I wanted to post something similar, but I'm hesitant because I think there's some funky stuff going on. http://nhforge.org/blogs/nhibernate/archive/2009/12/17/queryover-in-nh-3-0.aspx – Ani Jan 27 '11 at 13:02
  • Marc, the OP has posted the signature. I think you might be done with just a `Expression.Lambda>(Expression.TypeAs(body, typeof(object)), null)`. Not sure though, I think there's more to this than meets the eye. – Ani Jan 27 '11 at 13:38
  • @Ani - I would imagine it'll need explicit convert - will add – Marc Gravell Jan 27 '11 at 13:51
  • @Ani your version throws Cannot interpret member from (null.TotalPages As Object) – Andrej Slivko Jan 27 '11 at 13:52
  • As I mention, I think there's something strange here (from briefly looking at the QueryOver page), so this obvious approach may not work. I get the feeling it *wants* a closure so it can extract the name of the member of the *closure* class (the captured variable - `dto` in your example). No? – Ani Jan 27 '11 at 13:55
  • @Ani yes it cares only for name of prop – Andrej Slivko Jan 27 '11 at 13:56
  • i still would want something like Expression.FromString("() => x.y") from Microsoft :) I think it's not trivial at all, but that would simplify my life :) – Andrej Slivko Jan 27 '11 at 13:59
3

well use dynamic linq as you wrote, or use expression tree http://msdn.microsoft.com/en-us/library/bb397951.aspx

i don't think that there are other solutions

Kikaimaru
  • 1,791
  • 1
  • 14
  • 27
2

I managed to find one way myself, but it looks more of workaround, Marc's version is way more simpler. I will accept Marc's answer as soon as i will test it. Heres my workaround :

public class MemberModifier : ExpressionVisitor
{
    public Expression Modify(Expression expression)
    {
        return Visit(expression);
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        var t = typeof (DepartmentPaperConsumption);
        var memberInfo = t.GetMember("TotalPages")[0];
        return Expression.MakeMemberAccess(node.Expression, memberInfo);
    }
}

and then in code

        Expression<Func<object>> exp = () => dto.TotalColorPrints;
        var mod = new MemberModifier();
        var modEx = mod.Modify(exp);
        result.OrderByAlias((Expression<Func<object>>)modEx)

MemberModifier is only raw prototype, it should be more generic and not depend on DepartmentConsumption and without hardcoded "TotalPages"

Andrej Slivko
  • 1,236
  • 1
  • 12
  • 27