Get Property Name and Type Using Lambda Expression

Retrieving Property name from lambda expression

I found another way you can do it was to have the source and property strongly typed and explicitly infer the input for the lambda. Not sure if that is correct terminology but here is the result.

public static RouteValueDictionary GetInfo<T,P>(this HtmlHelper html, Expression<Func<T, P>> action) where T : class
{
var expression = (MemberExpression)action.Body;
string name = expression.Member.Name;

return GetInfo(html, name);
}

And then call it like so.

GetInfo((User u) => u.UserId);

and voila it works.

Get property name and type using lambda expression

Here's enough of an example of using Expressions to get the name of a property or field to get you started:

public static MemberInfo GetMemberInfo<T, U>(Expression<Func<T, U>> expression)
{
var member = expression.Body as MemberExpression;
if (member != null)
return member.Member;

throw new ArgumentException("Expression is not a member access", "expression");
}

Calling code would look like this:

public class Program
{
public string Name
{
get { return "My Program"; }
}

static void Main()
{
MemberInfo member = ReflectionUtility.GetMemberInfo((Program p) => p.Name);
Console.WriteLine(member.Name);
}
}

A word of caution, though: the simple statment of (Program p) => p.Name actually involves quite a bit of work (and can take measurable amounts of time). Consider caching the result rather than calling the method frequently.

Get a property name from a lambda expression *without* an object instance

You can use a property expression the same way as EditorFor. You can do this without an instance.

The one difference is you'll have to specify the type of the expression's parameter to tell the compiler what the object type is. So instead of

EditorFor( x => x.Name );    //Specifies a property but not a type

...your expression would look like this:

EditorFor( (MyType x) => x.Name ); //Specifies property and the type it belongs to

You can accomplish this with a short method like this one:

static PropertyInfo GetPropertyInfo<TIn, TOut>(Expression<Func<TIn, TOut>> expression)
{
var memberExp = expression.Body as MemberExpression;
return memberExp?.Member as PropertyInfo;
}

And then you can do this:

var p1 = GetPropertyInfo((string s) => s.Length);
Console.WriteLine("{0}.{1}", p1.DeclaringType.FullName, p1.Name);

var p2 = GetPropertyInfo((DateTime d) => d.Minute);
Console.WriteLine("{0}.{1}", p2.DeclaringType.FullName, p2.Name);

var p3 = GetPropertyInfo((Stream s) => s.CanSeek);
Console.WriteLine("{0}.{1}", p3.DeclaringType.FullName, p3.Name);

Output:

System.String.Length
System.DateTime.Minute
System.IO.Stream.CanSeek

Notice that we never needed any instances.

Pass property name by lambda expression for reading attribute values

You can split the work into two functions in order to bypass specifying all generic parameter type for a generic method restriction

public static object[] GetPropertyAttributes<TObject, TProperty>(
this TObject instance,
Expression<Func<TObject, TProperty>> propertySelector)
{
//consider handling exceptions and corner cases
var propertyName = ((PropertyInfo)((MemberExpression)propertySelector.Body).Member).Name;
var property = instance.GetType().GetProperty(propertyName);
return property.GetCustomAttributes(false);
}

public static T GetFirst<T>(this object[] input) where T : Attribute
{
//consider handling exceptions and corner cases
return input.OfType<T>().First();
}

then use it like

foo.GetPropertyAttributes(f => f.Bar)
.GetFirst<StringLengthAttribute>()
.MaximumLength;

Using lambda expression to get property OR type name

I've traced this back to the construction of the Expression. It doesn't really contain any instance information, and no way to get the type name.

static Expression<Func<object, object>> thisObject = x => x;

So there's no way that a type name can be derived from an Expression that doesn't even have a type (other than object).

The method used to generate an expression that returns a property name:

LambdaExpression BuildExpression(Type rootType, string propertyName)
{
try
{
var properties = propertyName.Split('.');
ParameterExpression arg = Expression.Parameter(rootType, "x");
Expression expr = arg;
foreach (string property in properties)
{
PropertyInfo propertyInfo = rootType.GetProperty(property);
if (propertyInfo == null)
return null;
expr = Expression.Property(expr, propertyInfo);
rootType = propertyInfo.PropertyType;
}
return Expression.Lambda(expr, arg);
}
catch (System.Exception ex)
{
return null;
}
}

How do I get property names of a type using a lambda expression and anonymous type?

I'm lazy so this code handles only public properties. But it should be a good base to get you started.

public static string[] Foo<T>(Expression<Func<T, object>> func)
{
var properties = func.Body.Type.GetProperties();

return typeof(T).GetProperties()
.Where(p => properties.Any(x => p.Name == x.Name))
.Select(p =>
{
var attr = (ColumnAttribute) p.GetCustomAttributes(typeof(ColumnAttribute), true).FirstOrDefault();
return (attr != null ? attr.Name : p.Name);
}).ToArray();
}

Retrieve property name from lambda expression in TypeScript

Unlike in C#, one can dynamically access properties by their name in JavaScript (and thus also Typescript), so you could just pass the name as a string to the function and use bracket notation to access the property:

myMethod(model, "userId")

Now the cool thing about typescript that this string can actually be typesafe:

function myMethod<T, K extends keyof T>(model: T, key: K) {
const value = model[key];
//...
}

Read on


If you really want to do something similar like you did in C# (don't!!) Just do this:

function myMethod(model: () => any) {
const key = model.toString().split(".")[1];
//...
}


Related Topics



Leave a reply



Submit