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
How to Set the Default Xml Namespace for an Xdocument
How to Set Timer Resolution from C# to 1 Ms
How to Use Reflection to Call Method by Name
How Can a Windows Service Start a Process When a Timer Event Is Raised
Removing Nodes from an Xmldocument
Jtoken: Get Raw/Original JSON Value
Retrieving Creation Date of File (Ftp)
How to Handle Session End in Global.Asax
Appending an Existing Xml File with Xmlwriter
How to Replace All the Spaces with %20 in C#
Finding Quoted Strings with Escaped Quotes in C# Using a Regular Expression
Async Process Start and Wait for It to Finish
C# - Realtime Console Output Redirection
Ef Code First: How to Get Random Rows