2

Using lambda delegate Expression> - where my expression takes a Role object (POCO).

Looking to use that POCO Role object and map it to a data layer Role object with matching properties. To do that, I need to be able to get the Role object from the delegate.

Example:

public List<Role> FindAll(Expression<Func<Role, bool>> filter)

Calling this method like:

FindAll(r => r.Name == role.Name);

r is type Role, and within the FindAll function, I can see that filter has one parameter, as such:

enter image description here

Can I extract that object? And how?

I'm sure it MUST be doable, after all, linq does it internally all the time...

The Evil Greebo
  • 7,013
  • 3
  • 28
  • 55
  • Why are you duplicating `Where`? – leppie Feb 01 '12 at 16:38
  • Have you tried casting them to the specialized `Expression`'s? – leppie Feb 01 '12 at 16:39
  • @leppie 1) What do you mean, 'Why am I duplicating `Where`? 2) Parameter[0] is of type ParameterExpression - so far I haven't found any properties off of that I can cast to my own type from, but I'm still trying. – The Evil Greebo Feb 01 '12 at 16:47
  • 2
    The debugger is listing all the types for you already. Just cast to that, and viola, you have the properties you see in the debugger. It is a fairly trivial task, no magic involved :) – leppie Feb 01 '12 at 16:52
  • No, it isn't. Filter is of type System.Linq.Expressions.LambdaExpression. Parameter[0] is of type ParameterExpression. The Type property on ParameterExpression is returning the Type of object represented, but not the actual object itself. Can't cast that. – The Evil Greebo Feb 01 '12 at 16:58
  • 1
    @TheEvilGreebo Why can’t you cast that, exactly? – Konrad Rudolph Feb 01 '12 at 16:59
  • Are you trying to determine the Type of the parameter? The reason why I ask is because you ask about extracting an object and there is no object to extract other than the delegate. – Roy Goode Feb 01 '12 at 17:05
  • (Role)filter yields: Cannot convert type 'System.Linq.Expressions.Expression>' to 'Entity.Role'. (Role)filter.Parameters[0] yields: (Role)filter.Parameters[0] Cannot convert type 'System.Linq.Expressions.ParameterExpression' to 'Entity.Role' – The Evil Greebo Feb 01 '12 at 17:05
  • @TheEvilGreebo it's a delegate parameter, not an object. You definitely can't cast it to a Role. i.e. there is no Role object. – Roy Goode Feb 01 '12 at 17:07
  • @RoyGoode Well, I'm hoping that since the delegate is using a Role object, there's a way to get a reference to the Role object the delegate is using. – The Evil Greebo Feb 01 '12 at 17:09
  • Followup: Right - I'm not trying to cast it. That was leppie's suggestion. I'm trying to get to the object that's being used inside the delegate itself. – The Evil Greebo Feb 01 '12 at 17:10
  • @TheEvilGreebo It's a delegate method expecting a parameter of type Role. Surely there's no Role object in existence until the method is invoked? e.g. Role myRoleObjectToInvokeTheMethod = new Role(); var compiledFilter = filter.Compile(); var resultValue = compiledFilter(myRoleObjectToInvokeTheMethod); – Roy Goode Feb 01 '12 at 17:11
  • @TheEvilGreebo You didn’t read properly. Nowhere did leppie say that you should cast to `Role` – of course you should cast to the appropriate type, which the debugger tells you (`ParameterExpression`). – Konrad Rudolph Feb 01 '12 at 17:19
  • @RoyGoode Sure but at invocation, the delegate method DOES have a parameter expression that knows about the underlying type its using (as in the T of Func). That underlying type has been instantiated in the invocation of the delegate - so I'm trying to get to it, if at all possible. – The Evil Greebo Feb 01 '12 at 17:20
  • @KonradRudolph You're right - I misunderstood leppie. Re-reading it, I guess I don't understand - what kind of specialized expression would I cast it to? – The Evil Greebo Feb 01 '12 at 17:23
  • @TheEvilGreebo OK, so you want to find out the Type in code: Type delegateParameterType = filter.Parameters[0].Type; – Roy Goode Feb 01 '12 at 17:25
  • @RoyGoode No, that wasn't what I was going for - but Bryan's answer crystallized it for me. Thanks anyway. – The Evil Greebo Feb 01 '12 at 17:35
  • @TheEvilGreebo No problem, I can see your response to Bryan's answer provides us with a better explanation of what you were trying to do. – Roy Goode Feb 01 '12 at 17:36

1 Answers1

2

There are two roles here: r, which represents the filter parameter, and role, which is an object that is closed over by the lambda expression. I assume you mean you want a reference to the role object, since you already found the ParameterExpression which represents r.

That object will be a ConstantExpression whose type is Role, and it will be the value of the Expression property of the MemberAccessExpression which represents role.Name. That will be the right-hand side of the BinaryOperator expression representing the equality test, which serves as the Body of the lambda expression.

Is that what you need?

Bryan Watts
  • 44,911
  • 16
  • 83
  • 88
  • Yes and no. No, it's not what I really wanted - but reading your explanation has helped crystallize why it won't work. (r=>r.name = role.name) is only one type of possible filters. I could just as easily say (r=>r.name="Fred") - which would never have a role object so of course, why would that object *be* there... – The Evil Greebo Feb 01 '12 at 17:34