从表达式中获取数组属性的属性名称

时间:2016-07-09 22:38:01

标签: c# .net asp.net-mvc tree expression

基本上我试图做一件非常简单的事情,但我无法弄明白,怎么做。 我试图从expresion获取属性名称,例如对于这个表达式我想得到结果:

  • PropertyName(e => e.Easy) ="简单"
  • PropertyName(e => e.Not.So.Easy) =" Not.So.Easy"
  • PropertyName(e => e.ImLost[i])其中i在for循环中变量=" ImLost [0]"," ImLost [1]",...

对于前两个,它相对容易,但对于第三个我迷失了,但我认为我不能成为第一个想要实现一样。你有什么建议或想法吗? PropertyName方法的签名遵循static string PropertyName<T, TProp>(Expression<Func<T, TProp>> expr) where T : class

1 个答案:

答案 0 :(得分:0)

以下将处理所有三种情况:

using System;
using System.Collections;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;

namespace PropertyNameFromExpression
{
    [TestClass]
    public class PropertyNameTests
    {
        [TestMethod]
        public void TestCanGetEasyExpression()
        {
            string propertyName = PropertyName<Source>(e => e.Easy);
            Assert.AreEqual("Easy", propertyName);
        }
        [TestMethod]
        public void TestCanGetNotSoEasyExpression()
        {
            string propertyName = PropertyName<Source>(e => e.Not.So.Easy);
            Assert.AreEqual("Not.So.Easy", propertyName);
        }
        [TestMethod]
        public void TestCanGetArrayExpressionWithConstantIndex()
        {
            string propertyName = PropertyName<Difficult>(e => e.ImLost[3]);
            Assert.AreEqual("ImLost["+3+"]", propertyName);
        }
        [TestMethod]
        public void TestCanGetArrayExpressionWithVariableIndex()
        {
            int i = 3;
            string propertyName = PropertyName<Difficult>(e => e.ImLost[i]);
            Assert.AreEqual("ImLost[" + i + "]", propertyName);
        }

        public string PropertyName<TSource>(Expression<Func<TSource, int>> expression)
        {
            return PropertyName(expression.Body);
        }

        private string PropertyName(Expression expression)
        {
            if (expression is BinaryExpression)
            {
                return PropertyName(expression as BinaryExpression);
            }
            if (expression is ConstantExpression)
            {
                return (expression as ConstantExpression).Value.ToString();
            }
            MemberExpression memberExpression = expression as MemberExpression;
            if (memberExpression.Expression is MemberExpression)
            {
                return PropertyName(memberExpression.Expression) + "." + memberExpression.Member.Name;
            }
            if (memberExpression == null)
            {
                throw new ArgumentException("Unknown Expression type:"+expression.GetType().Name);
            }
            if (memberExpression.Member.MemberType == MemberTypes.Field)
            {
                var f = Expression.Lambda(memberExpression).Compile();
                object value = f.DynamicInvoke();
                return value.ToString();
            }
            return memberExpression.Member.Name;
        }
        private string PropertyName(BinaryExpression binaryExpression)
        {
            if (typeof(IEnumerable).IsAssignableFrom(binaryExpression.Left.Type))
            {
                return PropertyName(binaryExpression.Left) + "[" + PropertyName(binaryExpression.Right) + "]";
            }
            return PropertyName(binaryExpression.Left) + "." + PropertyName(binaryExpression.Right);
        }

    }

    public class Source
    {
        public int Easy { get; set; }
        public Level2 Not { get; set; }
    }

    public class Level2
    {
        public Level3 So { get; set; }
    }
    public class Level3
    {
        public int Easy { get; set; }
    }

    public class Difficult
    {
        public int[] ImLost { get;set; }
    }
}