C# 我可以从Func获取特定元数据吗<;T、 对象>;?

C# 我可以从Func获取特定元数据吗<;T、 对象>;?,c#,.net,linq,generics,reflection,C#,.net,Linq,Generics,Reflection,考虑以下代码: 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" 字符串属性名称

考虑以下代码:

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"
字符串属性名称;
var dateList=new List(){DateTime.Now};
propertyName=dateList.GetPropertyName(dateTimeObject=>dateTimeObject.Hour);
//我希望propertyName变量现在包含字符串“Hour”
以下是扩展方法:

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
}
公共静态字符串GetPropertyName(此IList列表,Func Func){
//TODO:要动态确定
//属性正在func函数/lambda中使用
}
有办法做到这一点吗?我想,也许使用
Expression
而不是
Func
的另一种方法会给我更多的力量来找到我需要的东西,但我不知道如何找到

public static string GetPropertyName<T>(this IList<T> list, Expression<Func<T, object>> expr) {
   // interrogate expr to get what I want, if possible
}
公共静态字符串GetPropertyName(此IList列表,表达式expr){
//如果可能的话,询问expr以得到我想要的
}
这是我第一次对Linq做这么深的事情,所以我可能遗漏了一些明显的东西。基本上,我喜欢传入lambdas的想法,这样我就可以进行编译时检查,但我不知道我关于如何在这种特殊情况下使用它们的想法是否有效


谢谢

像这样的东西应该可以做到:

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;
}
公共静态字符串GetPropertyName(此IList列表,表达式expr){
MemberExpression member_expression=将主体表示为MemberExpression;
if(成员_表达式==null)
抛出新的ArgumentNullException(“成员表达式”);
MemberInfo member=member\u expression.member;
PropertyInfo property=作为PropertyInfo的成员;
字符串proname=memeber.name;
}

警告:航空代码

这是我使用的版本,它返回一个
PropertyInfo
,但是获取名称并不重要

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;
}
publicstaticpropertyinfo GetProperty(Expression)
{
MemberExpression MemberExpression=null;
if(expression.Body.NodeType==ExpressionType.Convert)
{
memberExpression=((UnaryExpression)expression.Body).操作数作为memberExpression;
}
else if(expression.Body.NodeType==ExpressionType.MemberAccess)
{
memberExpression=expression.Body作为memberExpression;
}
if(memberExpression==null)
{
抛出新ArgumentException(“非成员访问”、“表达式”);
}
返回memberExpression.Member作为PropertyInfo;
}

在这个博客上有一个非常简单快捷的方法:

因此:

Func Func=Name=> “价值”

您可以获得lambda参数 函数委托的“名称” 电话:

func.Method.GetParameters()[0]。名称 (将返回“Name”)

下面是来自 安德烈:

公共字典哈希(params Func[]args)
T:在哪里上课
{
var items=newdictionary();
foreach(参数中的var func)
{
var item=func(空);
添加(func.Method.GetParameters()[0]。名称,项);
}
退货项目;
}
希望有帮助,
Patrick

只是一个旁注:func.Method.GetParameters()[0]。与编译lambda并提取成员表达式、成员信息和名称相比,Name速度非常快

谢谢你回答内森,我很感激。你离得够近了,既然你说“像这样的事情应该会成功”,你从技术上讲并没有错!我将接受@gcores的回答,因为他的回答是正确的,我无需进行更改。不过我还是给了你+1分!Nathan和gcores在一些边缘情况下的回答有一点不同,比如可空小数(如果我没记错的话!)。对于这些属性,表达式的主体不是MemberExpression,而是一个UnaryExpression(在gcores的答案中处理)。@Jason太酷了,我会接受他的答案,因为它比我的答案更完整。@sighohwell:我知道,这就是为什么我接受了@gcores的答案,并且觉得@Nathan的答案足够好,值得一些赞扬,如果@gcores没有发布的话,它会帮我指明正确的方向。太棒了,这太完美了。现在我的破解完成了!:P啊,我讨厌不得不想出这些变通办法来让东西“像它应该的那样”工作。我的意思是,这很有趣,但当有真正的工作要做时,这太痛苦了。非常感谢。可能重复的
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;
}