5

私はこの種の形式で仕様を使用しています:

public static Expression<Func<User, bool>> IsSuperhero
{
  get
  {
    return x => x.CanFly && x.CanShootLasersFromEyes;
  }
}

これで、この仕様を次の形式で使用できます。

var superHeroes = workspace.GetDataSource<User>().Where(UserSpecifications.IsSuperhero);

しかし、次のような関連付けられたオブジェクトに対して仕様を使用する方法がわかりません。

var loginsBySuperheroes = workspace.GetDataSource<Login>().Where(x => x.User [ ??? ]);

これを行う方法はありますか、または仕様の実装を再考する必要がありますか?

4

4 に答える 4

4

Expression<Func<Login, bool>>基本的に、関連するユーザーをログインから収集し、IsSuperheroそのユーザーに既存の述語を適用する を作成する必要があります。これを達成する標準的な方法はExpression.Invoke、「含まれる」式 (IsSuperHeroこの場合) で使用し、そのパラメーターを適切な引数に置き換えることです。

残念ながら、このアプローチを手動で行うのは非常に面倒です。さらに悪いことに、LINQ to Entities などの多くの LINQ プロバイダーは、この種の「式内の式」アプローチをまったく好みません。これを回避する方法は、「呼び出された」式をより大きな式に「インライン化」して、すべてが単一の巨大な式ツリーのように見えるようにすることです。

幸いなことに、これに役立つ便利なライブラリLINQKitがあります。

#region LINQKit Magic

Expression<Func<Login, bool>> predicate = login => IsSuperHero.Invoke(login.User);
var expandedPredicate = predicate.Expand(); 

#endregion LINQKit Magic

var loginsBySuperheroes = workspace.GetDataSource<Login>().Where(expandedPredicate);
于 2011-11-08T12:50:04.880 に答える
2

明らかに:

var loginsBySuperheroes = workspace.GetDataSource<User>()
  .Where(UserSpecifications.IsSuperhero)
  .SelectMany(x => x.Logins);

これは楽しいかもしれません:

var secretBillionaires = workspace.GetDataSource<User>()
   .Where(UserSpecifications.IsSuperhero)
   .SelectMany(user => user.Logins)
   .Where(LoginSpecifications.IsSecretIdentity)
   .Select(login => login.DayJob)
   .Where(DayJobSpecifications.IsBillionaire)
于 2011-11-08T15:29:38.597 に答える
0

ここで詳細に説明されているように、独自のカスタム QueryProvider を作成できます: http://msdn.microsoft.com/en-us/library/bb546158.aspx

于 2011-11-08T11:54:01.350 に答える
0

式をコンパイルしてから呼び出す必要があると思います。

var loginsBySuperheroes = GetLogins().Where(l => IsSuperhero.Compile().Invoke(l.User));

別の方法として、式をプリコンパイルすることもできます。

var f = IsSuperhero.Compile();
var loginsBySuperheroes = GetLogins().Where(l => f(l.User));
于 2011-11-08T11:54:22.787 に答える