Reputation: 6431
//ModelFor(person =>person.Name);
public void ModelFor<TModel, TValue>(
Expression<Func<TModel, TValue>> expression)
{
//Result should be "Name"
string nameOfTValue = ????;
}
Upvotes: 8
Views: 5164
Reputation: 47607
@Ani: I don't think this is right, I think that he wants the name of the parameter in the expression of type TValue
If this is true... this works 1 level deep only but might be handy anyway:
var nameOfTValue = ((MemberExpression)expression.Body).Member.Name;
Here is smarter implementation that should be able to deal with multiple levels:
public class PropertyName{
public static string For<T>(
Expression<Func<T,object>> expression){
var body=expression.Body;
return GetMemberName(body);
}
public static string For(
Expression<Func<object>> expression){
var body=expression.Body;
return GetMemberName(body);
}
public static string GetMemberName(
Expression expression){
if(expression is MemberExpression){
var memberExpression=(MemberExpression)expression;
if(memberExpression.Expression.NodeType==
ExpressionType.MemberAccess)
return GetMemberName(memberExpression.Expression)
+"."+memberExpression.Member.Name;
return memberExpression.Member.Name;
}
if(expression is UnaryExpression){
var unaryExpression=(UnaryExpression)expression;
if(unaryExpression.NodeType!=ExpressionType.Convert)
throw new Exception(string.Format
("Cannot interpret member from {0}",expression));
return GetMemberName(unaryExpression.Operand);
}
throw new Exception
(string.Format("Could not determine member from {0}",expression));
}
}
Usage:
var fieldName=PropertyName.For<Customer>(x=>x.Address.Region);
//fieldName==Address.Region
Another trick, this can be combined with reflection nicely:
public static T Set<T,TProp>(this T o,
Expression<Func<T,TProp>> field,TProp value){
var fn=((MemberExpression)field.Body).Member.Name;
o.GetType().GetProperty(fn).SetValue(o,value,null);
return o;
}
Allows to directly set properties with ease, can be useful for test fixtures:
var customer=new Customer("firstName","lastName");
customer.Set(x=>x.Name, "different firstName");
Upvotes: 9
Reputation: 113422
EDIT: After your edit, I think you are want the name of the member involved in the expression, assuming of course that the expression is a member-expression in the first place.
((MemberExpression)expression.Body).Member.Name
To be more robust, you can do:
var memberEx = expression.Body as MemberExpression;
if (memberEx == null)
throw new ArgumentException("Body not a member-expression.");
string name = memberEx.Member.Name;
(Not relevant anymore):
To get a System.Type
that represents the type of the TValue
type-argument, you can use the typeof
operator.
You probably want:
typeof(TValue).Name
But also consider the FullName
and AssemblyQualifiedName
properties if appropriate.
This really has nothing to do with expression-trees; you can use this technique to get the type of a type-argument for any generic method.
Upvotes: 11