Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get specific metadata from a Func<T, object>?

Consider the following code:

string propertyName;
var dateList = new List<DateTime>() { DateTime.Now };
propertyName = dateList.GetPropertyName(dateTimeObject => dateTimeObject.Hour);

// I want the propertyName variable to now contain the string "Hour"

Here is the extension method:

public static string GetPropertyName<T>(this IList<T> list, Func<T, object> func) {
   //TODO: would like to dynamically determine which 
   // property is being used in the func function/lambda
}

Is there a way to do this? I thought that maybe this other method, using Expression<Func<T, object>> instead of Func<T, object> would give me more power to find what I need, but I am at a loss at how.

public static string GetPropertyName<T>(this IList<T> list, Expression<Func<T, object>> expr) {
   // interrogate expr to get what I want, if possible
}

This is the first time I have done anything this deep with Linq, so maybe I am missing something obvious. Basically I like the idea of passing in lambdas, so that I get compile-time checking, but I don't know that my idea on how I can use them in this particular case will work.

Thanks

like image 270
Jason Bunting Avatar asked Feb 24 '09 00:02

Jason Bunting


3 Answers

This is the version I use, it returns a PropertyInfo, but getting the name is trivial.

public static PropertyInfo GetProperty<T>(Expression<Func<T, object>> expression)  
{
    MemberExpression memberExpression = null;

    if (expression.Body.NodeType == ExpressionType.Convert)
    {
        memberExpression = ((UnaryExpression) expression.Body).Operand as MemberExpression;
    }
    else if (expression.Body.NodeType == ExpressionType.MemberAccess)
    {
        memberExpression = expression.Body as MemberExpression;
    }

    if (memberExpression == null)
    {
        throw new ArgumentException("Not a member access", "expression");
    }

    return memberExpression.Member as PropertyInfo;
}
like image 177
gcores Avatar answered Nov 05 '22 19:11

gcores


here is a very easy and fast way to do it on this blog: http://blog.bittercoder.com/PermaLink,guid,206e64d1-29ae-4362-874b-83f5b103727f.aspx

So given:

Func func = Name => "Value";

You can get the lambda parameter "Name" from the function delegate by calling:

func.Method.GetParameters()[0].Name (would return "Name")

Here's the revised Hash method from Andrey:

public Dictionary<string, T> Hash<T>(params Func<string, T>[] args)
where T : class
{
    var items = new Dictionary<string, T>();
    foreach (var func in args)
    {
        var item = func(null);
        items.Add(func.Method.GetParameters()[0].Name, item);
    }
    return items;
}

Hope it helps, Patrick

like image 31
Patrick Wolf Avatar answered Nov 05 '22 18:11

Patrick Wolf


Something like this should do the trick:

public static string GetPropertyName<T>(this IList<T> list, Expression<Func<T, object>> expr) {
  MemberExpression member_expression = expr.Body as MemberExpression;
  if (member_expression == null)
      throw new ArgumentNullException("member_expression");
  MemberInfo member = member_expression.Member;
  PropertyInfo property = member as PropertyInfo;
  string proname = memeber.name;
}

WARNING: Air Code!

like image 36
Nathan W Avatar answered Nov 05 '22 18:11

Nathan W