8

私はここで c# と linq の知識の限界を押し広げているので、私の例や、linq、c#、ジェネリック型、ラムダ式、デザイン パターンなどの理解が完全に間違っている場合は、ご容赦ください。

2 つのコレクションを保持するクラスがあります。1 つはフィルター処理IEnumberable<InstagramUser>するコレクションで、2 つ目はフィルター処理する式のコレクションです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()

public class UserFilter : IInstagramFilter {
    public Expression<Func<T, bool>> filter<T>(IQueryable<T> source) {
        //return some expression - but how?
    }
}

私はいくつかのことを理解するのに苦労しています:

  1. IInstagramFilterクラスの式を設定してメソッドで呼び出すdisplay()方法は?

  2. IInstagramFilterクラスにはフィルタリングに使用されるラムダがありますが、 Filter クラスには適切なラムダを最初に作成する方法IEnumerable<InstagramUser>に関する知識がないため?IEnumerable<InstagramUser>

  3. これは大まかにデコレータパターンに沿っていると思いますが、おそらく私が気付いていないより良いデザインが一緒にあるかもしれません.

更新されたコード

オリヴィエの答えに基づいて、これが私が今持っているものです。使用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()各アイテムに対してアクションを実行しますが、returnタイプが無効であり、何も返しません。

この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以上のすべてのユーザーが返されます。これにより、ユーザーが2回返される可能性があるため、.Distinct()

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