使用 lambda 表达式获取 属性 或类型名称
Using lambda expression to get property OR type name
当 lambda 表达式引用实际实例本身时,我如何调整下面的方法来工作?
例如而不是
x => x.Name
表达式是
x => x
所以如果我有一些 class "Car" 我可以 return 字符串 "Car" 而不是只能对其属性进行操作(例如 Car.Colour)
方法:
public static string GetMemberName(Expression expression)
{
if (expression is LambdaExpression)
expression = ((LambdaExpression)expression).Body;
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));
}
即我想要这样的东西:
if (expression is SomeExpressionThatReturnsAnInstance)
{
return (name of type of instance);
}
可能是我误会了,直接x => x
就是ParameterExpression
。只需在您现有的 is MemberExpression
测试下添加一个额外的测试:
if (expression is MemberExpression)
{
// As-is
}
// New condition
if (expression is ParameterExpression)
{
return expression.Type.Name;
}
使用此代码:
class Car { public string Color { get; set; }}
Expression<Func<Car, string>> expr1 = x => x.Color;
Expression<Func<Car, Car>> expr2 = x => x;
Console.WriteLine(GetMemberName(expr1));
> Color
Console.WriteLine(GetMemberName(expr2));
> Car
如果你确定像 x=>x 这样的表达式,那么你甚至不需要在正文中看到,只需获取像
这样的参数
((LambdaExpression)expression).Parameters.First().Type.Name
你也可以添加条件如
if(expression is ParameterExpression){
return ((ParameterExpression)expression).Type
}
我已经将其追溯到表达式的构造。它实际上不包含任何实例信息,也无法获取类型名称。
static Expression<Func<object, object>> thisObject = x => x;
因此,无法从甚至没有类型(对象除外)的表达式派生类型名称。
用于生成returns一个属性名称的表达式的方法:
LambdaExpression BuildExpression(Type rootType, string propertyName)
{
try
{
var properties = propertyName.Split('.');
ParameterExpression arg = Expression.Parameter(rootType, "x");
Expression expr = arg;
foreach (string property in properties)
{
PropertyInfo propertyInfo = rootType.GetProperty(property);
if (propertyInfo == null)
return null;
expr = Expression.Property(expr, propertyInfo);
rootType = propertyInfo.PropertyType;
}
return Expression.Lambda(expr, arg);
}
catch (System.Exception ex)
{
return null;
}
}
//Use generics for more information!
public static string GetMemberName<T, TValue>(Expression<Func<T, TValue>> expression)
{
if (expression is LambdaExpression)
expression = ((LambdaExpression)expression).Body;
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;
}
//Magic part...
if (typeof(T) == typeof(TValue))
{
return typeof(T).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));
}
当 lambda 表达式引用实际实例本身时,我如何调整下面的方法来工作?
例如而不是
x => x.Name
表达式是
x => x
所以如果我有一些 class "Car" 我可以 return 字符串 "Car" 而不是只能对其属性进行操作(例如 Car.Colour)
方法:
public static string GetMemberName(Expression expression)
{
if (expression is LambdaExpression)
expression = ((LambdaExpression)expression).Body;
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));
}
即我想要这样的东西:
if (expression is SomeExpressionThatReturnsAnInstance)
{
return (name of type of instance);
}
可能是我误会了,直接x => x
就是ParameterExpression
。只需在您现有的 is MemberExpression
测试下添加一个额外的测试:
if (expression is MemberExpression)
{
// As-is
}
// New condition
if (expression is ParameterExpression)
{
return expression.Type.Name;
}
使用此代码:
class Car { public string Color { get; set; }}
Expression<Func<Car, string>> expr1 = x => x.Color;
Expression<Func<Car, Car>> expr2 = x => x;
Console.WriteLine(GetMemberName(expr1));
> Color
Console.WriteLine(GetMemberName(expr2));
> Car
如果你确定像 x=>x 这样的表达式,那么你甚至不需要在正文中看到,只需获取像
这样的参数((LambdaExpression)expression).Parameters.First().Type.Name
你也可以添加条件如
if(expression is ParameterExpression){
return ((ParameterExpression)expression).Type
}
我已经将其追溯到表达式的构造。它实际上不包含任何实例信息,也无法获取类型名称。
static Expression<Func<object, object>> thisObject = x => x;
因此,无法从甚至没有类型(对象除外)的表达式派生类型名称。
用于生成returns一个属性名称的表达式的方法:
LambdaExpression BuildExpression(Type rootType, string propertyName)
{
try
{
var properties = propertyName.Split('.');
ParameterExpression arg = Expression.Parameter(rootType, "x");
Expression expr = arg;
foreach (string property in properties)
{
PropertyInfo propertyInfo = rootType.GetProperty(property);
if (propertyInfo == null)
return null;
expr = Expression.Property(expr, propertyInfo);
rootType = propertyInfo.PropertyType;
}
return Expression.Lambda(expr, arg);
}
catch (System.Exception ex)
{
return null;
}
}
//Use generics for more information!
public static string GetMemberName<T, TValue>(Expression<Func<T, TValue>> expression)
{
if (expression is LambdaExpression)
expression = ((LambdaExpression)expression).Body;
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;
}
//Magic part...
if (typeof(T) == typeof(TValue))
{
return typeof(T).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));
}