8

我在这里挑战了我在 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); 
}

我会让课程扩展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?
    }
}

我正在努力理解一些事情:

  1. 如何为每个IInstagramFilter类设置表达式,然后在display()方法中调用它?

  2. 每个IInstagramFilter类都有一个用于过滤的 lambda,IEnumerable<InstagramUser>但由于 Filter 类不知道IEnumerable<InstagramUser>我将如何首先创建适当的 lambda?

  3. 我认为这大致遵循装饰者模式,但也许有一个更好的设计,我不知道。

更新代码

根据 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
    }
}
4

1 回答 1

6

您必须决定是要执行某些操作还是要返回某些内容。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);

如果您有用户来源,您可以对所有过滤器返回的所有用户执行类似操作

IQueryable<InstagramUser> usersSource = ...; 
// Or IEnumerable<InstagramUser> for LINQ to objects
// if you drop the Expression<> part.

var users = userFilters.SelectMany(f => usersSource.Where(f));

SelectMany展平嵌套的枚举。该示例返回名称以“A”开头或得分 >= 100 的所有用户。这可能会返回一个用户两次,因此我建议附加一个.Distinct()

var users = userFilters
    .SelectMany(f => usersSource.Where(f))
    .Distinct();
于 2012-08-23T20:11:10.473 回答