使Linq函数更通用的参数

时间:2019-08-20 19:37:37

标签: c# .net linq generics .net-core

如何概括此功能?我希望[1549] 96650006, 966543799, 966500080 [1401] 96650006, 966567865, 966500069, 966500071 属性是可变的,并具有接受函数,将person类替换为任何类。

Name

其他项目:

// Filtering logic  
Func<SampleFilterModel, IEnumerable<Person>> filterData = (filterModel) =>  
{  
    return persons.Where(p => p.Name.StartsWith(filterModel.Term ?? String.Empty, StringComparison.InvariantCultureIgnoreCase))  
       .Skip((filterModel.Page-1) * filter.Limit)  
       .Take(filterModel.Limit);  
};  

当前尝试,尝试根据需要进行修改/返工:

出现一些问题/错误:

  1. 我是否必须将所有变量声明为静态变量?

  2. 获取错误消息:

      

    'T'不包含'propertyInfo'的定义,找不到可以接受的扩展方法'propertyInfo'接受类型为'T'的第一个参数(您是否缺少using指令或程序集引用?)

代码:

IEnumerable<Person> persons = new List<Person>() {
    new Person() { Name = "Laura Callahan", DOB = DateTime.Parse("1958-01-09"), Email = "laura.callahan@test.com" },
    new Person() { Name = "Anne Dodsworth", DOB = DateTime.Parse("1966-01-27"), Email = "anne.dodsworth@test.com" }
};

public class SampleFilterModel
{
    public int Page { get; set; }
    public int Limit { get; set; }
    public string Term { get; set; }

    public SampleFilterModel()
    {
        this.Page = 1;
        this.Limit = 3;
    }

    public object Clone()
    {
        var jsonString = JsonConvert.SerializeObject(this);
        return JsonConvert.DeserializeObject(jsonString, this.GetType());
    }
}

1 个答案:

答案 0 :(得分:1)

尽管其余问题对我而言意义不大,但尝试创建泛型函数的部分将需要为Where调用建立一个谓词

查看其中的注释以获取如何构建用于谓词的lambda表达式的示例

public static class Filterclass {
    static readonly MethodInfo startsWith = typeof(string).GetMethod("StartsWith", new[] { typeof(string), typeof(System.StringComparison) });

    public static IEnumerable<T> FilterData<T>(this IEnumerable<T> input, string columnName, FilterModel filterModel) where T : class {
        var type = typeof(T);
        var propertyInfo = type.GetProperty(columnName);
        //T p =>
        var parameter = Expression.Parameter(type, "p");
        //T p => p.ColumnName
        var name = Expression.Property(parameter, propertyInfo);
        // filterModel.Term ?? String.Empty
        var term = Expression.Constant(filterModel.Term ?? String.Empty);
        //StringComparison.InvariantCultureIgnoreCase
        var comparison = Expression.Constant(StringComparison.InvariantCultureIgnoreCase);
        //T p => p.ColumnName.StartsWith(filterModel.Term ?? String.Empty, StringComparison.InvariantCultureIgnoreCase)
        var methodCall = Expression.Call(name, startsWith, term, comparison);

        var lambda = Expression.Lambda<Func<T, bool>>(methodCall, parameter);

        return input.Where(lambda.Compile())
        .Skip((filterModel.Page - 1) * filterModel.Limit)
        .Take(filterModel.Limit);
    }
}

现在,这假定该列为字符串类型。任何其他类型都会导致此异常。

您还需要假设p不是null,否则当尝试在空引用上调用实例成员时,将再次引发空引用异常。

正在使用的扩展方法的样本单元测试

[TestClass]
public class MyTestClass2 {
    [TestMethod]
    public void MyTestMethod() {
        //Arrange
        IEnumerable<Person> persons = new List<Person>() {
            new Person() { Name = "Nancy Davolio", DOB = DateTime.Parse("1948-12-08"), Email = "nancy.davolio@test.com" },
            new Person() { Name = "Andrew Fuller", DOB = DateTime.Parse("1952-02-19"), Email = "andrew.fuller@test.com" },
            new Person() { Name = "Janet Leverling", DOB = DateTime.Parse("1963-08-30"), Email = "janet.leverling@test.com" },
            new Person() { Name = "Margaret Peacock", DOB = DateTime.Parse("1937-09-19"), Email = "margaret.peacock@test.com" },
            new Person() { Name = "Steven Buchanan", DOB = DateTime.Parse("1955-03-04"), Email = "steven.buchanan@test.com" },
            new Person() { Name = "Michael Suyama", DOB = DateTime.Parse("1963-07-02"), Email = "michael.suyama@test.com" },
            new Person() { Name = "Robert King", DOB = DateTime.Parse("1960-05-29"), Email = "robert.king@test.com" },
            new Person() { Name = "Laura Callahan", DOB = DateTime.Parse("1958-01-09"), Email = "laura.callahan@test.com" },
            new Person() { Name = "Anne Dodsworth", DOB = DateTime.Parse("1966-01-27"), Email = "anne.dodsworth@test.com" }
        };

        var filter = new FilterModel {                
            Term = "Nancy"
        };

        //Act
        var data = persons.FilterData("Name", filter);

        //Assert
        data.Should().NotBeEmpty();
    }
}