【问题标题】:c# Lambda Expression - Get property value from string [duplicate]c# Lambda 表达式 - 从字符串中获取属性值
【发布时间】:2016-07-14 16:44:18
【问题描述】:

考虑以下 lambda 表达式:

IQueryable<Product> query = query.Where(x => x.ProductName.Contains("P100"));

我需要将上面的代码转换成这样:

IQueryable<Product> query = query.Where(x => x.GetPropertyValue("ProductName").Contains("P100"));

这里我添加了一个虚拟方法GetPropertyValue("ProductName") 来解释需求。 在上面的代码中,属性应该在运行时解析。换句话说,我需要从一个字符串值访问该属性,例如 "ProductName"

我该怎么做?

【问题讨论】:

  • 我的意思是我必须让这个方法更通用。根据我的应用程序逻辑,我只有属性名称作为字符串值。所以我需要将字符串解析为属性。
  • 您的查询处理器是什么?它甚至支持在Product 对象上使用GetPropertyValue() 方法吗?如果不支持,则进行转换是没有意义的。
  • 你需要学习Linq Expressions,或者你需要使用Dynamic Linq。
  • @DavidG 这与您所引用的问题完全不同,因为大多数 Linq 提供程序无法使用反射。

标签: c# linq lambda iqueryable


【解决方案1】:
var parameterExp = Expression.Parameter(typeof(Product), "type");
var propertyExp = Expression.Property(parameterExp, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var someValue = Expression.Constant(propertyValue, typeof(string));
var containsMethodExp = Expression.Call(propertyExp, method, someValue);

Expression<Func<Product, bool>> predicate = Expression.Lambda<Func<T, bool>>
             (containsMethodExp, parameterExp);


var query = query.Where(predicate);

【讨论】:

  • 这可以轻松转移到没有包含位的 linq where 调用吗?
  • @DouglasGaskell 没有包含位是什么意思?上面的代码用于生成一个没有任何 CLR 的纯 Linq 表达式树。这允许此查询在大多数 Linq 提供程序中运行,包括非 CLR 支持的提供程序,如 EF 或 nHiberate。
【解决方案2】:

你可以有这个扩展方法:

public static T GetPropertyValue<T>(this Product product, string propName)
{
   return (T)typeof(Product).GetProperty(propName).GetValue(product, null);
}

然后:

IQueryable<Product> query = query.Where(x => x.GetPropertyValue<string>("ProductName").Contains("P100"));

请注意,这不适用于 Entity Framework 查询数据库,但由于您没有使用实体框架标记问题,我不假设您正在使用它

【讨论】:

  • 我正在使用 Odata V4 和 Odata 客户端代码生成器。这行得通吗?
  • 我从未使用过,我不知道,但如果它与问题相关(确实如此),您应该指定它(或至少标记问题)
猜你喜欢
  • 2022-01-15
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 2017-03-21
  • 2016-08-13
  • 2020-09-29
  • 1970-01-01
相关资源
最近更新 更多