C# 从表达式中获取字符串属性名

C# 从表达式中获取字符串属性名,c#,.net,asp.net-mvc,lambda,C#,.net,Asp.net Mvc,Lambda,我正在尝试编写一个强类型助手 可能是这样的: Html.Lookup(x => x.FooId); 现在我有这个: public static MvcHtmlString Lookup<T,TReturn>(this HtmlHelper<T> html, Func<T, TReturn> expression) { // get string "FooId" here } publicstaticmvchtmlstring查找(此HTML

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

Html.Lookup(x => x.FooId);
现在我有这个:

public static MvcHtmlString Lookup<T,TReturn>(this HtmlHelper<T> html, Func<T, TReturn> expression)
{
     // get string "FooId" here
}
publicstaticmvchtmlstring查找(此HTMLHelperHTML,Func表达式)
{
//在这里获取字符串“FooId”
}
有人知道如何得到这个吗?

还有另一个代码

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;
    }
}
public MvcHtmlString Lookup<T, TReturn>(this HtmlHelper<T> html, Expression<Func<T, TReturn>> expression)
{
  return MvcHtmlString.Create(ExpressionHelper.GetExpressionText(expression));
}
public MvcHtmlString查找(此HtmlHelper html,表达式)
{
返回MvcHtmlString.Create(ExpressionHelper.GetExpressionText(表达式));
}
使用ExpressionHelper类。 Func是委托,表达式是在编译时生成表达式树。
Expression.Compile()返回委托,但Func在运行时未获取ExpressionTree。

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

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));
    }
  }
}
namespace Interreg.Domain{
使用制度;
使用System.Linq.Expressions;
公共类PropertyName{
的公共静态字符串(
表达式(表达式){
var body=expression.body;
返回GetMemberName(body);
}
的公共静态字符串(
表达式(表达式){
var body=expression.body;
返回GetMemberName(body);
}
公共静态字符串GetMemberName(
表达式(表达式){
if(表达式为MemberExpression){
var memberExpression=(memberExpression)表达式;
如果(memberExpression.Expression.NodeType==
ExpressionType.MemberAccess)
返回GetMemberName(memberExpression.Expression)+“+”memberExpression.Member.Name;
返回memberExpression.Member.Name;
}
if(表达式为一元表达式){
var unaryExpression=(unaryExpression)表达式;
if(unaryExpression.NodeType!=ExpressionType.Convert)
抛出新异常(string.Format(“无法解释来自{0}的成员”,表达式));
返回GetMemberName(unaryExpression.Operator);
}
抛出新异常(string.Format(“无法确定来自{0}的成员,表达式));
}
}
}

这一个的好处是——当深入到一个级别以上时,它不会丢失点。

有点晚了,但我在.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;
    }
publicpropertyinfo GetPropertyInfo(表达式propertyLambda){
var member=propertyLambda.Body作为MemberExpression;
if(member==null){//值类型返回无法转换为MemberExpression的Convert(x.property)
var expression=propertyLambda.Body作为一元表达式;
member=表达式。操作数作为MemberExpression;
}
返回成员。成员作为PropertyInfo;
}

我认为这应该行得通,但看起来我没有正确地声明我的表达式,或者是因为我不能使用它我想要的
return memberExpression==null?null:memberExpression.Member.Name这不适用于值类型。带值类型的表达式将是沿着“{x=>Convert(x.Property)}”的内容。您需要将其强制转换为UnaryExpression,然后将其操作数强制转换为MemberExpression。@slawek谢谢!为了一个小时可能重复的问题,你一直在努力解决这个问题,你为什么要重新发明
ViewData.ModelMetadata
?@Craig Stuntz我真的不明白你的意思,我只想创建一个强类型的帮助器你正在为已经存在的功能创建一个帮助器。从您的问题来看,不清楚您正试图通过这样做来解决什么问题。可能的重复也会返回“Class.PropertName”,与上面接受的答案相反。
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;
    }