简体   繁体   English

如何在运行时将属性放入linq表达式?

[英]How can I put a property to linq expression at runtime?

I need to pass property name to the "GetClientsByFilter()" method via string parameter "propertyName" and use this property in LINQ expression. 我需要通过字符串参数“ propertyName”将属性名称传递给“ GetClientsByFilter()”方法,并在LINQ表达式中使用此属性。

It is assumed that there is need to use reflection. 假定需要使用反射。

Do you have any idea what I have to use instead string that with comment "//pseudo code" below? 您是否知道我必须在下面使用带注释“ // pseudo code”的字符串代替什么? Thanks. 谢谢。

public class Client
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

internal class DataLayer
{
  public static List<Client> GetClientsByFilter(string search, string propertyName)
  {
     //it's Entity Framework context
     using (var dbContext = new LibDbContext())
        {
            List<Client> clients;

                 clients = dbContext.Clients
                .Where(item => item.[propertyName].Contains(search)) // pseudo code
                .ToList();
        }
     return clients;
  }
}

You can pass instead of property yet another lambda which gets the property value: 您可以传递另一个获取属性值的lambda而不是属性:

public static List<Client> GetClientsByFilter(string search, 
                                              Func<Client, string> propertyGetter)
{
  //it's Entity Framework context
  using (var dbContext = new LibDbContext())
  {
    List<Client> clients;

    clients = dbContext.Clients
                       .Where(item => propertyGetter(item).Contains(search))
                       .ToList();
  }
  return clients;
}

Unfortunately, this approach cannot be used when you get the property name from "outside" and cannot build the proper lambda for getting the value. 不幸的是,当您从“外部”获取属性名称时,无法使用此方法,并且无法构建适当的lambda来获取值。 In such case you can prepare a dictionary of lambdas for each property name. 在这种情况下,您可以为每个属性名称准备一个lambda字典。

If you want to use reflection, please see the answer here 如果要使用反射,请在此处查看答案

I have solved this problem like this: 我已经解决了这样的问题:

    public static List<Client> GetClientsByFilter(string search, string propertyName)
    {
        using (var dbContext = new LibDbContext())
        {     
            List<Client> clients;

              switch (propertyName)
              {
                case "LastName":

                  clients = dbContext.Clients
                      .Where(item => item.LastName.Contains(search))
                      .ToList();
                break;

                case "FirstName":

                  clients = dbContext.Clients
                      .Where(item => item.FirstName.Contains(search))
                      .ToList();
                break;
              }
           return clients;
        } 

But I want to rewrite this code and will make it more clearly without copy/paste 但是我想重写这段代码,并且无需复制/粘贴即可使其更加清晰

This is an almost-duplicate question of " How do I create an expression tree to represent 'String.Contains("term")' in C#? ." 这是一个几乎重复的问题,“ 如何在C#中创建一个表达式树来表示'String.Contains(“ term”)'?” Marc's answer provides this bit of code to build an expression, which is what you are looking for: Marc的答案提供了以下代码来构建表达式,这就是您要查找的内容:

static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue)
{
    var parameterExp = Expression.Parameter(typeof(T), "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);

    return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);
}

...and now using it from your method: ...现在从您的方法中使用它:

public static List<Client> GetClientsByFilter(string search, string propertyName)
{
   //it's Entity Framework context
   using (var dbContext = new LibDbContext())
   {
        List<Client> clients;

             clients = dbContext.Clients
            .Where(GetExpression<Client>(propertyName, search)) // Now using Marc's method
            .ToList();
    }
 return clients;

} }

Since "GetExpression" is generic, you can easily reuse this for other types besides just Client . 由于“ GetExpression”是通用的,因此除了Client之外,您还可以轻松地将其重用于其他类型。 Consider renaming the method since "GetExpression" doesn't spell out your intent - maybe something like "GetPropertyContainsExpression". 考虑重命名该方法,因为“ GetExpression”并不能说明您的意图,例如“ GetPropertyContainsExpression”之类的东西。 You might also consider adding some error handling to that method in case the value in propertyName is not a valid property on the type and when the property specified isn't of type string which probably wouldn't have a Contains method that takes a string. 如果propertyName中的值不是该类型上的有效属性,并且当指定的属性不是string类型(可能没有采用字符串的Contains方法)时,您也可以考虑对该方法添加一些错误处理。 These sorts of errors might be hard to figure out from the exceptions the expression builder might throw at run time. 从表达式构建器在运行时可能引发的异常中,可能很难弄清这些错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Linq进行多重属性Lambda表达式 - How can I make a Multiple property lambda expression with Linq 如何将过滤器发送到 linq 表达式? - How can i send filter to linq expression? 如何编写这个 LINQ 表达式? - How can I compose this LINQ expression? 如何让用户在运行时指定在 Linq-to-Objects GroupBy 查询表达式中使用哪些实体属性? - How can I let users specify which entity properties are used in a Linq-to-Objects GroupBy query expression at runtime? 如何编写对属性方法进行过滤的LINQ表达式树? - How do I write a LINQ Expression Tree that filters on a method of a property? 如何将IQueryable表达式对象转换为LINQ表达式? - How can I convert IQueryable expression object into LINQ expression? 运行时创建LINQ表达式 - Runtime creation of LINQ expression 我可以在Linq表达式中将String参数用作实体属性和对象属性吗? - Can I use String parameter as an entity property and an object property in Linq expression? 如何在运行时动态组合一组LINQ查询? - How can I dynamically combine a set of LINQ queries at runtime? 我可以对字符串进行条件检查以查看它是否在LINQ表达式内以“ 00”结尾吗? - Can I put a conditional check on a string to see if it ends in “00” inside a LINQ expression?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM