C# 列表的动态位置<;T>;

C# 列表的动态位置<;T>;,c#,linq-to-entities,C#,Linq To Entities,我正在尝试为各种类创建一个动态过滤器。我们只会在运行时知道所处理的类型。我需要ColumnName是实际的列(不是字符串值) 有没有简单的方法将字符串转换为列 public static List<T> Filter<T> (this List<T> Source, string ColumnName, string TypeOfCompare, string CompValue) { IQueryable<T> matc

我正在尝试为各种类创建一个动态过滤器。我们只会在运行时知道所处理的类型。我需要ColumnName是实际的列(不是字符串值)

有没有简单的方法将字符串转换为列

public static List<T> Filter<T>
    (this List<T> Source, string ColumnName, 
    string TypeOfCompare, string CompValue)
{
    IQueryable<T> matches = Source.AsQueryable();

    if (ColumnName.Length > 0)
    {
        matches = (IEnumerable)matches.Where(a => ColumnName == CompValue)
    }

    List<T> ReturnList2 = new List<T>();
    ReturnList2 = matches.ToList();
    return ReturnList2;
}
公共静态列表过滤器
(此列表源、字符串列名称、,
字符串类型(比较,字符串值)
{
IQueryable matches=Source.AsQueryable();
如果(ColumnName.Length>0)
{
matches=(IEnumerable)matches.Where(a=>ColumnName==CompValue)
}
List ReturnList2=新列表();
ReturnList2=matches.ToList();
返回列表2;
}

基本上,您需要构建一个表达式树。幸运的是,使用它并不难。您可以将其传递给
Queryable.Where
,也可以编译并传递给
Enumerable.Where
。(显然,您需要使用 同样,这取决于您试图进行的比较类型。)

CompValue
是实际值吗?公司的
类型是什么

我也不确定LINQ to实体在哪里适合这个。。。据我所知,你只使用LINQ来处理对象

编辑:好的,这是一个例子。它假设你想要平等,但如果是这样,它会做你想要的。我不知道每次编译表达式树对性能的影响是什么-您可能希望缓存任何给定名称/值组合的委托:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

static class Extensions
{
    public static List<T> Filter<T>
        (this List<T> source, string columnName, 
         string compValue)
    {
        ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
        Expression property = Expression.Property(parameter, columnName);
        Expression constant = Expression.Constant(compValue);
        Expression equality = Expression.Equal(property, constant);
        Expression<Func<T, bool>> predicate =
            Expression.Lambda<Func<T, bool>>(equality, parameter);

        Func<T, bool> compiled = predicate.Compile();
        return source.Where(compiled).ToList();
    }
}

class Test
{
    static void Main()
    {
        var people = new[] {
            new { FirstName = "John", LastName = "Smith" },
            new { FirstName = "John", LastName = "Noakes" },
            new { FirstName = "Linda", LastName = "Smith" },
            new { FirstName = "Richard", LastName = "Smith" },
            new { FirstName = "Richard", LastName = "Littlejohn" },
        }.ToList();

        foreach (var person in people.Filter("LastName", "Smith"))
        {
            Console.WriteLine(person);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Linq.Expressions;
静态类扩展
{
公共静态列表过滤器
(此列表源、字符串列名称、,
字符串(值)
{
ParameterExpression参数=表达式参数(类型为(T),“x”);
Expression property=Expression.property(参数、列名);
表达式常数=表达式常数(compValue);
表达式相等=表达式。相等(属性,常量);
表达式谓词=
Lambda(等式,参数);
Func compiled=谓词.Compile();
返回source.Where(compiled.ToList();
}
}
课堂测试
{
静态void Main()
{
var people=new[]{
新的{FirstName=“John”,LastName=“Smith”},
新的{FirstName=“John”,LastName=“Noakes”},
新的{FirstName=“Linda”,LastName=“Smith”},
新的{FirstName=“Richard”,LastName=“Smith”},
新的{FirstName=“Richard”,LastName=“Littlejohn”},
}.ToList();
foreach(var person in people.Filter(“LastName”、“Smith”))
{
控制台。写线(人);
}
}
}

而不是字符串
ColumnName
,您不能为该列传递一个选择器吗(我意识到这并不总是可能的,但只是以防万一?那么你可以用这个

顺便说一下,代码太复杂了。这应该起作用:

public static List<T> Filter<T>(
    this List<T> Source, Func<T, string> selector, string CompValue)
{
    return Source.Where(a => selector(a) == CompValue).ToList();
}

你在找这样的东西吗: 否则,您必须单独处理每个案例,如下所示:

if (columnName == "blah")
  matches = matches.Where(i => i.Blah == Value);
if (columnName == "name")
  matches = matches.Where(i => i.Name == Value);

正确的。。。这是Linq对对象的。。。我们有一些类包含诸如(firstname、lastname、phone)之类的数据,CompValue是我们希望匹配的实际值……因此,举个例子。。。personCollection=personCollection.Filter(“姓氏”、“史密斯”);我们会退回史密斯的“过滤”收藏。。。谢谢你。。。谢谢你,乔恩。我认为最好将参数compValue的类型从“string”改为“object”,以防需要等于整数或字符串。公共静态列表筛选器(此列表源、字符串列名、对象compValue)@Delmonte:我从问题中获取签名。我很可能会使它更通用(添加一个类型参数),而不是只接受对象。如果我的matches变量是运行时类型的dynamic list,该怎么办?
if (columnName == "blah")
  matches = matches.Where(i => i.Blah == Value);
if (columnName == "name")
  matches = matches.Where(i => i.Name == Value);