Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict lambda expression argument to the properties of a class

Tags:

c#

lambda

I have a base class which needs to process the names of the properties of derived classes (explicit access). To do so, I created a method which takes a lambda expression as input:

private string GetMemberName(Expression<Func<object>> expression)
{
    //gets the property name (MemberExpression or UnaryExpression)
    //out of scope
    return propertyName;
}

This allows me to call the method like so:

derived.GetMemberName(() => derived.MyPropertyInt);
derived.GetMemberName(() => derived.MyPropertyStr);

The problem is that object is not restrictive at all. I can also call:

derived.GetMemberName(() => "something"); //does not "return" anything but compiles (out of scope)
derived.GetMemberName(() => anotherClass.RandomMember); //not derived from "base"

How can I restrict the GetMemberName method so that it can only accept as input the members of the classes which derive from my base class? Setting GetMemberName(Expression<Func<MyBaseClass>> expression) restricts access to an entire class. Setting GetMemberName(Expression<Func<MyBaseClass, object>> expression) restricts access to the current instance but still allows "random" objects to be passed.

EDIT: The comment for derived.GetMemberName(() => "something"); was in the context of returning the property name, not the "value" of the lambda expression. The GetPropertyName method does not return anything, due to the fact that I'm only analyzing MemberExpression or UnaryExpression.

like image 472
Andrei V Avatar asked Dec 16 '13 08:12

Andrei V


1 Answers

How can I restrict the GetMemberName method so that it can accept only members of the classes which derive from my base class?

It's not clear what you mean by "accept" here, but if you're trying to restrict the set of valid lambda expressions to ones which uses members of your class, you can't. Lambda expressions and expression trees happen to be useful for getting this information, but that's not what they're designed for, so there are no specific features accommodating this. You'll always be able to use a lambda expression which doesn't just use a property.

The simplest approach is probably just to check this at execution time. You won't be able to stop people abusing your method at compile-time, but so long as it's simple to do the right thing, I wouldn't worry too much about callers doing the wrong thing - just make the error message really clear.

like image 63
Jon Skeet Avatar answered Sep 29 '22 12:09

Jon Skeet