0

私はクラスを持っていますProduct

class Product
{ 
   int Id { get; set; }
   string Name { get; set; }
   int CategoryId { get; set; }
   int PlantId { get; set; }
   DateTime ProductionDate { get; set; }
}

複数のプロパティでを使用したいのですがLINQ GroupBy、どのプロパティがいくつあるか事前にわかりません。CategoryIdたとえば、 のみ、PlantIdまたは両方でグループ化したい場合があります。LINQ GrouBy を動的に使用する方法を説明しているネット上の記事を見つけました。

これは確かにうまくいくかもしれませんが、事前に粒度を知らずに Group ByProductionDate.Yearを実行したい場合はどうなりますか? ProductionDate.Month粒度とは、特定の年に生産されたすべてのものをグループ化するかProducts、グループを月ごとに絞り込むかを意味します。

私が見つけた唯一の論理的な解決策は次のとおりです。

public ProductInfo GetGroupedProducts(int? year, int? month, int? selectedCategoryId, int? selectedPlantId)
{
List<Product> products = GetProducts();

var groupedProducts = products.GroupBy(p => new { (year == null ? p.ProductionDate.Year : string.Empty),
                                                  (month == null ? p.ProductionDate.Month : string.Empty),
                                                  (selectedCategoryId == null ? p.CategoryId : string.Empty),
                                                  (selectedPlantId == null ? p.PlantId : string.Empty)
});

//perform some additional filtering and assignments 

}

しかし、よりクリーンで適切な解決策があると思います。文字列に基づいてクエリを作成する古いスタイルの方法を使用すると、このタスクははるかに簡単に実行できました。LINQ他に方法がない場合、これは改善が必要な部分だと本当に思います。

4

2 に答える 2

0

よりクリーンな解決策は、次の拡張メソッドを使用することです。

public static TResult With<TInput, TResult>(this TInput? o, Func<TInput, TResult>
    selector, TResult defaultResult = default(TResult)) where TInput : struct
{
    return o.HasValue ? selector(o.Value) : defaultResult;
}

このような:

string result = year.With(T => p.ProductionDate.Year, string.Empty);

このうち、nullが問題ない場合:

string result = year.With(T => p.ProductionDate.Year);

または価値がある場合に備えTint何か。int?


しかし、ご存知のとおり、より良い解決策があります。分析できるように、コードを自由に拡張してください。

于 2012-12-03T11:57:07.747 に答える
0

あなたが求めていることを理解していれば、Linq Field<T> を使用するために typeof を逆にする同様の問題がありました

私は次のようなことをします

public static IEnumerable<IGrouping<string, TElement>> GroupMany<TElement>(
    this IEnumerable<TElement> elements, 
    params Func<TElement, object>[] groupSelectors)
    {
        return elements.GroupBy(e => string.Join(":", groupSelectors.Select(s => s(e))));
    }

次に、次のように関数を呼び出すことができます

var groupedProducts = products.GroupMany(p => p.CategoryId , p => p.ProductionDate.Month);

関数は、コロンで区切られたプロパティの文字列を介してグループ化されます。これを行った理由は、文字列のハッシュコードがクラスとは対照的に同じであることが保証されているためです。

于 2012-12-04T08:30:21.597 に答える