日期:2014-05-17  浏览次数:20821 次

一个关于泛型+lambda+反射 的复杂问题,求解~

首先,请看asp.net mvc中一个极其简单的例子,如果你没学过MVC,忽略这个例子
我定义了一个简单的Model类

  public class Model {
  public int Name { get; set; }
  }

然后在视图里:
@model MvcApplication1.Models.Model
@Html.LabelFor(g=>g.Name)

显示的结果是 Name,而这个Name这是我想要的效果
因为我想仿照LabelFor方法的调用方式,通过委托这个参数实现获取类的成员名称

问题是一直找不到合适的方法(应该是通过反射)获取
因为好像是要获取方法体的返回参数并找到其原属类的成员——即对应传入参数对象里面的成员。。。

C# code


    public class Model 
    {
        public int Name { get; set; }
    }

    public class GenericModel<T> { 
        public string GetModelPropertyName<TProperty> (Func<T,TProperty> PropertyExpr)
        {
            string result = "";

            //...这里该如何通过传进来的lambda获取成员名称,即获得result等于Name

            return result;
        }
    }

    class Program {
        static void Main(string[] args) {
            //调用方式
            GenericModel<Model> m = new GenericModel<Model>();
            Console.WriteLine(m.GetModelPropertyName(g => g.Name));
        }
    }







------解决方案--------------------
C# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Diagnostics.Contracts;
using System.Reflection;

namespace LambdaCallFunc
{
    class Program
    {
        static void Main(string[] args)
        {
            var test = new GenericModel<Test>();
            var pName = test.GetModelPropertyName(g => g.Name);
            Console.WriteLine(pName);
            Console.Read();
        }
        
    }

    class Test
    {
        public string Name { get; set; }
    }

    public class GenericModel<T>
    {
        public string GetModelPropertyName<TProperty>(Expression<Func<T, TProperty>> propertyExpr)
        {
            var path = propertyExpr.GetMemberPathString();
            return path;
        }
    }

    public static class ExpressionExtensions
    {
        public static String GetMemberPathString<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> expression)
        {
            Contract.Requires(expression != null);
            Contract.Requires(expression.Body.NodeType == ExpressionType.MemberAccess);
            MemberExpression body = expression.Body as MemberExpression;

            LinkedList<string> rval = new LinkedList<string>();

            while (body != null)
            {
                var propertyName = (body.Member is PropertyInfo) ? body.Member.Name : null;
                if (!string.IsNullOrEmpty(propertyName)) rval.AddFirst(propertyName);
                body = body.Expression as MemberExpression;
            }

            return String.Join(".", rval);
        }
    }
}