tags:

views:

78

answers:

1

I'm trying to pass in a property of a Linq entity to be used by my method. I can easily pass a property to be queried

Func<Entities.MyEntity, ResultType> GetProperty = ent => ent.Property;

However this returns ResultType and cannot be used to set the property.

I thought about using reflection to get a propertyInfo, but this will let me fetch the property but then I can't use Linq syntax to call my property. Is there any guru out there that knows how to do this?

I have a hunch I could do it by constructing a chunk of an expression tree and applying it onto the query...

I was really hoping to do something like:

var value = myQueryEntity.CallMagicFunction();  //typesafe
myQueryEntity.CallMagicFunction() = value; //typesafe
+2  A: 

Indeed, an expression tree should work; for basic member access (a field/property directly off the object):

static MemberInfo ReadMember(LambdaExpression expr)
{
    if(expr == null) throw new ArgumentNullException("expr");
    MemberExpression me = expr.Body as MemberExpression;
    if(me == null || !ReferenceEquals(me.Expression, expr.Parameters[0])) {
        throw new ArgumentException("expr");
    }
    return me.Member;
}

with

Expression<Func<Customer, int>> func = c => c.Id;
MemberInfo member = ReadMember(func);
// for simplicity assume prop:
PropertyInfo prop = (PropertyInfo)member;

From there you can do pretty much anything; in particular you can get the get/set accessors (if you want to create a delegate), or use GetValue / SetValue.

Note that in .NET 4.0 you can set properties directly on an Expression (but the C# compiler doesn't add any extra support for this, so you'd need to write your own Expression by hand).

Marc Gravell
So this uses an expression tree and reflection to access the propertyinfo object. I realise that I can call the member and set the member from here. I would have thought that there would be a typesafe way of doing this without resorting to the getvalue/setvalue. Or should I start programming in python...
Spence
@Spence - sure; just use `obj.Id = ...` ;-p OK, more seriously, you can create a typed delegate - for example a `Func<Customer,int>` / `Action<Customer,int>` by using `Delegate.CreateDelegate` - is that what you would need? In 4.0 `dynamic` may also be of interest.
Marc Gravell