【问题标题】:Get string property name from expression从表达式中获取字符串属性名称
【发布时间】:2011-04-16 06:27:38
【问题描述】:

我正在尝试编写一个强类型的助手 这将是这样的:

Html.Lookup(x => x.FooId);

现在我有这个:

public static MvcHtmlString Lookup<T,TReturn>(this HtmlHelper<T> html, Func<T, TReturn> expression)
{
     // get string "FooId" here
}

有人知道怎么弄吗?

【问题讨论】:

标签: c# .net asp.net-mvc lambda


【解决方案1】:
public static class ExpressionsExtractor
{
    public static string Lookup<T, TProp>(this HtmlHelper<T> html, Expression<Func<T, TProp>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;

        if (memberExpression == null)
            return null;

        return memberExpression.Member.Name;
    }
}

然后你会调用它:

var propName = Html.Lookup(x => x.FooId);

【讨论】:

  • 我认为这应该可以,但看起来我没有正确声明我的表达方式,或者因为我无法使用我想要的内容
  • return memberExpression == null ? null : memberExpression.Member.Name;
  • 这不适用于值类型。带有值类型的表达式将沿着“{x => Convert(x.Property)}”。您需要将其转换为 UnaryExpression,然后将其操作数转换为 MemberExpression。
  • @slawek 谢谢!已经为此苦苦挣扎了一个小时
【解决方案2】:

又一个代码。

public MvcHtmlString Lookup<T, TReturn>(this HtmlHelper<T> html, Expression<Func<T, TReturn>> expression)
{
  return MvcHtmlString.Create(ExpressionHelper.GetExpressionText(expression));
}

使用 ExpressionHelper 类。 Func 是委托,Expression 是在编译时生成 ExpressionTree。 Expression.Compile() 返回委托,但 Func 在运行时没有得到 ExpressionTree。

【讨论】:

  • 这也返回与上面接受的答案相反的“Class.PropertName”。
【解决方案3】:

当我在不应该存在 System.Web.Mvc 引用的 Web 项目之外需要此功能时,目前正在使用此类:

namespace Interreg.Domain{
  using System;
  using System.Linq.Expressions;
  public class PropertyName{
    public static string For<T>(
      Expression<Func<T,object>> expression){
      var body=expression.Body;
      return GetMemberName(body);
    }
    public static string For(
      Expression<Func<object>> expression){
      var body=expression.Body;
      return GetMemberName(body);
    }
    public static string GetMemberName(
      Expression expression){
      if(expression is MemberExpression){
        var memberExpression=(MemberExpression)expression;
        if(memberExpression.Expression.NodeType==
           ExpressionType.MemberAccess)
          return GetMemberName(memberExpression.Expression)+"."+memberExpression.Member.Name;
        return memberExpression.Member.Name;
      }
      if(expression is UnaryExpression){
        var unaryExpression=(UnaryExpression)expression;
        if(unaryExpression.NodeType!=ExpressionType.Convert)
          throw new Exception(string.Format("Cannot interpret member from {0}",expression));
        return GetMemberName(unaryExpression.Operand);
      }
      throw new Exception(string.Format("Could not determine member from {0}",expression));
    }
  }
}

关于这一点的好处是 - 它在深入一层时不会丢失点。

【讨论】:

    【解决方案4】:

    有点晚了,但我发布了一个在 .Net 4 中对我有用的简单解决方案。它在第 4 行处理值类型

    public PropertyInfo GetPropertyInfo<TSource>(Expression<Func<TSource, object>> propertyLambda) {
            var member = propertyLambda.Body as MemberExpression;
            if (member == null) {// value types return Convert(x.property) which can't be cast to MemberExpression
                var expression = propertyLambda.Body as UnaryExpression;
                member = expression.Operand as MemberExpression;
            }
            return member.Member as PropertyInfo;
        }
    

    【讨论】:

      猜你喜欢
      • 2013-08-17
      • 2013-08-21
      • 1970-01-01
      • 2011-09-30
      • 2016-07-14
      • 2023-01-08
      • 1970-01-01
      相关资源
      最近更新 更多