Aousaf Rashid
Aousaf Rashid

Reputation: 5738

C# Select property with name

I am not sure how to word this question properly, so apologies at the very beginning.

I am working with MongoDb and at some point, I need to design a lambda expression as follows:

...Set(g => g.Profile.First_Name, "Test");

Now, g refers to a class called User, which has a property of type Profile(a different class), with the same name Profile. As you can see, in the lambda expression, I am selecting the First_Name property and then passing the value "Test" to it.

My Question: Is there a way to select the property by name?

In more detail - is something like this possible? :

 .... g.Profile. ("First_Name")

As I am typing this, even to me it sounds ridiculous, but I need to dynamically select the particular properties therefore I need to select them via their names.

How do I actually achieve this?

I tried :

g.Profile.GetType().GetProperty("First_Name")

But it doesn't seem to be equivalent to g.Profile.First_Name.

Any ideas on what can be done?

Upvotes: 2

Views: 754

Answers (1)

p.s.w.g
p.s.w.g

Reputation: 149020

I probably don't actually want to use reflection here.

The g => ... is not actually a lambda function, but an expression tree — it's some fancy syntactic sugar for describing a process, in this case, a process for getting a certain property given a record of type User. MongoDB API provides overloads that allow expression so you can code 90% of your operations more gracefully, but if you really need to be dynamic you can of course bypass this, for example:

var setName = Builders<User>.Update.Set(g => g.Profile.First_Name, "Test");

Is roughly equivalent to something like:

var setName = Builders<User>.Update.Set("profile.first_name", "Test");

Of course, if you have BsonProperty attributes on your properties, custom conventions, etc. that can change the path of the BSON being updated.

Now, suppose you don't want to have to hard-code the BSON paths. Well, you can generate dynamic expression trees, but it's not very elegant or performant. You'd use something along the lines of this:

ParameterExpression param = Expression.Parameter(typeof(User), "g");
Expression<Func<User, String>> expr =
    Expression.Lambda<Func<User, String>>(
        Expression.Property(
            Expression.Property(
                param,
                "Profile"
            ),
            "First_Name"
        ),
        new[] { param }
    );

 var setName = Builders<User>.Update.Set(expr, "Test");

Upvotes: 3

Related Questions