Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get parent property from Expression function

So let's say that I have the following classes:

public class Model {
    public AnotherModel InnerModel {
        get;
        set;
    }
}

public class AnotherModel {
    public String Value{
        get;
        set;
    }
}

Now I have the following function:

public static void Foo<T, U>(Expression<Func<T, U>> func) {
     // Get the property info from func
}

What I would like to do now is the following:

Foo<Model, String>(o => o.InnerModel.Value)

Here comes the problem:

I know that you can fetch the PropertyInfo from the expression func by doing:

PropertyInfo propertyInfo = (PropertyInfo)((MemberExpression)func.Body).Member;

This will get me the PropertyInfo of the Value property. However, I would also like to get information about the parent property, that is the InnerModel property.

What I know so far is that I can do the following:

((MemberExpression)func.Body).Expression

to fetch information of the parent property. However, it doesn't seem to be possible to extract a PropertyInfo from the Expression itself.

Is there some way of actually retrieving the PropertyInfo of the Expression?

Edit: To clarify, and it might be a bad way of attempting it but here goes: I can't use EntityFramework for this, just to make sure that that is understood.

There is a database which I need to communicate with through an API.

This database got the usual relations like the manner: Table Thread UserID -> Users.UserID

This now extract to models. To follow the above example:

class Thread {
    [Reference(USER_USERID)]
    [TableKey(THREAD_USERID)]
    public User user {
        get;set;
    }
}

class User {
     [TableKey(USER_USERID)]
     public int UserId {
         get;set;
     }
}

Now I would like to make queries to this. So I thought "Hey, let's use expressions to simplify for the end user on how to ask for stuff, yay."

So, we could do something like EqualTo(o => o.user.UserId, 1);

However, since the TableKey property differs from the reference key I need to first fetch from the database the userId from the Thread table and then with that Id start asking the User table for information with that id.

Maybe this clarifies the purpose of all this, or maybe it don't.

like image 464
Ekenstein Avatar asked Nov 12 '14 15:11

Ekenstein


1 Answers

As you have already determined, the body of the expression is a MemberExpression. There are two properties of a MemberExpression that we need to look at.

The first is the Member property. This the MemberInfo being called. In your example this the Value property. The second property that we need to look at is the Expression property. This is what the member expression is being called on. In your example, this is {o.InnerModel}.

{o.InnerModel} is another MemberExpression. The Member is InnerModel, and the Expression is o.

Here is some code to get the chain of MemberInfos

public static void Foo<T, U>(Expression<Func<T, U>> func)
{
    var memberExp = func.Body as MemberExpression;
    while (memberExp != null)
    {
        var memberInfo = memberExp.Member;
        Console.WriteLine(memberInfo.Name);
        memberExp = memberExp.Expression as MemberExpression;
    }
}

When called like this:

Foo<Model, String>(o => o.InnerModel.Value);

it will output:

  • Value
  • InnerModel

This:

Foo<Assembly, int>(a => a.EntryPoint.DeclaringType.AssemblyQualifiedName.Length);

will output:

  • Length
  • AssemblyQualifiedName
  • DeclaringType
  • EntryPoint
like image 141
Andrew Radford Avatar answered Oct 08 '22 12:10

Andrew Radford