I'm pushing the limits of my knowledge in c# and linq here, so please bear with me if I'm completely off with my example or understanding of linq, c#, generic types, lambda expressions,design patterns, etc.
I have a class that holds two collections, one is the collection to be filtered: IEnumberable<InstagramUser>
and the second is the collection of expressions to filter on: 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);
}
I would have classes extend IInstagramFilter
. Each IInstagramFilter
class would have a property (or function - not sure what's best) that would return the lambda expression that would be applied to IEnumerable<InstagramUser>
in the display()
method.
public class UserFilter : IInstagramFilter {
public Expression<Func<T, bool>> filter<T>(IQueryable<T> source) {
//return some expression - but how?
}
}
I'm struggling to understand a few things:
How to set the expression for each
IInstagramFilter
class and then call it in thedisplay()
method?Each
IInstagramFilter
class would have a lambda that would be used to filterIEnumerable<InstagramUser>
but since the Filter class has no knowledge ofIEnumerable<InstagramUser>
how would I create the appropriate lambda in the first place?I think this roughly follows the Decorator Pattern but perhaps there's a better design all together that I'm not aware of.
UPDATED CODE
Based on Olivier's answer this is what I have now. On the return for display()
I'm getting the error when using .Where(filter)
The type arguments for method '
System.Linq.Enumerable.Where<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)
' cannot be inferred from the usage. Try specifying the type arguments explicitly.
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
}
}
IInstagramFilter
is unnecessary here. Instead ofSelectMany
couldn't he loop over the collection of filters, appending the.Where(filter)
touserSource
. This would prevent duplicate users, and also chain the filters together using "and" instead of "or" – Ketubim