bfl*_*mi3 7 c# linq lambda expression
我在c#和linq这里推动了我的知识极限,所以如果我完全偏离我的例子或对linq,c#,泛型类型,lambda表达式,设计模式等的理解,请耐心等待.
我有一个包含两个集合的类,一个是要过滤的集合:IEnumberable<InstagramUser>第二个是要过滤的表达式集合:IEnumerable<IInstagramFilter>.
public class InstagramDisplay {
public IEnumerable<InstagramUser> instagramUsers;
public IEnumerable<IInstagramFilter> instagramFilters;
public InstagramDisplay() {
instagramUsers = new List<InstagramUser>();
instagramFilters = new List<IInstagramFilter>();
}
public IEnumerable<InstagramUser> display() {
instagramFilters.ToList().ForEach(x => instagramUsers.Where(x.filter(instagramUsers)));
return instagramFilters;
}
}
public interface IInstagramFilter {
Expression<Func<T, bool>> filter<T>(IQueryable<T> source);
}
Run Code Online (Sandbox Code Playgroud)
我会扩展课程IInstagramFilter.每个IInstagramFilter类都有一个属性(或函数 - 不确定什么是最好的),它将返回将IEnumerable<InstagramUser>在display()方法中应用的lambda表达式.
public class UserFilter : IInstagramFilter {
public Expression<Func<T, bool>> filter<T>(IQueryable<T> source) {
//return some expression - but how?
}
}
Run Code Online (Sandbox Code Playgroud)
我很难理解一些事情:
如何为每个IInstagramFilter类设置表达式,然后在display()方法中调用它?
每个IInstagramFilter类都有一个用于过滤的lambda,IEnumerable<InstagramUser>但由于Filter类不知道IEnumerable<InstagramUser>我将如何创建适当的lambda?
我认为这大致遵循装饰模式,但也许有一个更好的设计,我不知道.
更新的代码
根据Olivier的回答,这就是我现在所拥有的.在返回时,display()我在使用时收到错误.Where(filter)
方法'
System.Linq.Enumerable.Where<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)' 的类型参数不能从用法中推断出来.尝试显式指定类型参数.
public class InstagramDisplay {
public IEnumerable<InstagramUser> instagramUsers;
public List<Expression<Func<InstagramUser, bool>>> instagramFilters;
public InstagramDisplay() {
instagramUsers = new List<InstagramUser>();
instagramFilters = new List<Expression<Func<InstagramUser, bool>>>();
}
public void addFilter(Expression<Func<InstagramUser, bool>> filter) {
instagramFilters.Add(filter);
}
public IEnumerable<InstagramUser> display() {
return instagramFilters.SelectMany(filter => instagramUsers.Where(filter)).Distinct(); //error on this line
}
}
Run Code Online (Sandbox Code Playgroud)
您必须决定是要执行某些操作还是要返回某些内容。List<T>.ForEach()对每个项目执行操作,但是返回类型为void,并且不返回任何内容。
这个IInstagramFilter接口对我来说似乎是多余的。您可以这样声明一个过滤器列表
var userFilters = new List<Expression<Func<InstagramUser, bool>>>();
userFilters.Add(u => u.Name.StartsWith("A"));
userFilters.Add(u => u.Score >= 100);
Run Code Online (Sandbox Code Playgroud)
如果您有用户来源,则可以对所有过滤器返回的所有用户执行类似的操作
IQueryable<InstagramUser> usersSource = ...;
// Or IEnumerable<InstagramUser> for LINQ to objects
// if you drop the Expression<> part.
var users = userFilters.SelectMany(f => usersSource.Where(f));
Run Code Online (Sandbox Code Playgroud)
SelectMany展平嵌套枚举。该示例返回名称以“ A”开头或分数> = 100的所有用户。这可能会使用户返回两次,因此我建议附加一个.Distinct()
var users = userFilters
.SelectMany(f => usersSource.Where(f))
.Distinct();
Run Code Online (Sandbox Code Playgroud)