【问题标题】:Can I get specific metadata from a Func<T, object>?我可以从 Func<T, object> 获取特定的元数据吗?
【发布时间】:2009-02-24 00:15:20
【问题描述】:

考虑以下代码:

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"

扩展方法如下:

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
}

有没有办法做到这一点?我想也许这种其他方法,使用Expression&lt;Func&lt;T, object&gt;&gt; 而不是Func&lt;T, object&gt; 可以让我更有能力找到我需要的东西,但我不知道怎么做。

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

这是我第一次用 Linq 做这么深的事情,所以也许我遗漏了一些明显的东西。基本上我喜欢传入 lambdas 的想法,这样我就可以进行编译时检查,但我不知道我在这种特殊情况下如何使用它们的想法是否可行。

谢谢

【问题讨论】:

标签: c# .net linq generics reflection


【解决方案1】:

这是我使用的版本,它返回一个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;
}

【讨论】:

  • 太棒了,这太完美了。现在我的 hack 完成了! :P 啊,我讨厌不得不想出这些变通办法来让东西“像它应该的那样”工作。我的意思是,这很有趣,但是当有真正的工作要做时太痛苦了。谢谢!
【解决方案2】:

在此博客上有一个非常简单快捷的方法:http://blog.bittercoder.com/PermaLink,guid,206e64d1-29ae-4362-874b-83f5b103727f.aspx

所以给定:

Func func = 名称 => “价值”;

可以获取 lambda 参数 来自函数委托的“名称” 调用:

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

这是修改后的 Hash 方法 安德烈:

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;
}

希望对你有帮助, 帕特里克

【讨论】:

    【解决方案3】:

    这样的事情应该可以解决问题:

    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;
    }
    

    警告:航空代码!

    【讨论】:

    • 感谢您回答 Nathan,非常感谢。您已经足够接近了,既然您说“这样的事情应该可以解决问题”,那么您在技术上并没有错!我会接受@gcores 的回答,因为他是正确的,无需我进行更改。不过,我仍然给了你一个 +1 的回答!
    • Nathan 和 gcores 的答案在一些边缘情况(如可空小数)方面存在细微差别(如果我没记错的话!)。对于这些属性,表达式的主体不是 MemberExpression 而是 UnaryExpression(在 gcores 的答案中处理)。
    • @Jason 太酷了,我会接受他的回答,而且它比我的更完整。
    • @sighohwell:我知道,这就是为什么我接受@gcores 的回答并认为@Nathan 的回答足够好,值得称赞,因为如果@gcores 会帮助我指明正确的方向还没有发布。
    【解决方案4】:

    附带说明:func.Method.GetParameters()[0].Name 与编译 lambda 并提取成员表达式、成员信息和名称相比非常快.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多