How do I generalize this function? I want Name
property to be variable, and have function accept, replace the persons class with any class.
// 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);
};
Other items:
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());
}
}
Current attempt, trying to modify/rework as needed:
giving some problems/errors:
Do I have to declare all variables as static?
Getting error message:
'T' does not contain a definition for 'propertyInfo' and no accessible extension method 'propertyInfo' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)
Code:
public class Filterclass<T> where T : class
{
public static string ColumnName;
public static SampleFilterModel filter = new SampleFilterModel();
public static IEnumerable<T> input;
public Func<SampleFilterModel, IEnumerable<T>> filterData = (filterModel) =>
{
var propertyInfo = input.GetType().GetProperty(ColumnName);
return input.Where(p => p.propertyInfo.StartsWith(filterModel.Term ?? String.Empty, StringComparison.InvariantCultureIgnoreCase))
.Skip((filterModel.Page - 1) * filter.Limit)
.Take(filterModel.Limit);
};
}
While the rest of the question does not make much sense to me, the part about trying to make a generic function would require building up a predicate for the Where
call
Review the comments included to get an example of how to build up the lambda expression used for the predicate
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);
}
}
Now this assumes that the column is of type string. Any other type would cause this to throw an exception.
You would also need to assume that p
is not null
else again a null reference exception will be thrown when trying to call instance members on a null reference.
Sample unit test of the extension method in use
[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();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.