从数组 属性 的表达式中获取 属性 名称
Get property name from expression for array property
基本上我正在尝试做非常简单的事情,但我不知道该怎么做。
我正在尝试从表达式中获取 属性 名称,例如对于这个表达式我想得到结果:
PropertyName(e => e.Easy)
= "Easy"
PropertyName(e => e.Not.So.Easy)
= "Not.So.Easy"
PropertyName(e => e.ImLost[i])
其中 i 在 for 循环中是变量 = "ImLost[0]", "ImLost[1]", ...
前两个比较容易,但是第三个我迷路了,但我想我不能成为第一个,想要达到同样的目标。你有什么建议或想法吗?
属性Name 方法的签名在 static string PropertyName<T, TProp>(Expression<Func<T, TProp>> expr) where T : class
.
之后
以下将处理所有三种情况:
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; }
}
}
基本上我正在尝试做非常简单的事情,但我不知道该怎么做。 我正在尝试从表达式中获取 属性 名称,例如对于这个表达式我想得到结果:
PropertyName(e => e.Easy)
= "Easy"PropertyName(e => e.Not.So.Easy)
= "Not.So.Easy"PropertyName(e => e.ImLost[i])
其中 i 在 for 循环中是变量 = "ImLost[0]", "ImLost[1]", ...
前两个比较容易,但是第三个我迷路了,但我想我不能成为第一个,想要达到同样的目标。你有什么建议或想法吗?
属性Name 方法的签名在 static string PropertyName<T, TProp>(Expression<Func<T, TProp>> expr) where T : class
.
以下将处理所有三种情况:
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; }
}
}