式を受け取り、それを SQL データベースに対して分析するカスタム IQueryProvider クラスを作成しました (Linq2Sql を使用できることはわかっていますが、残念ながら Linq2Sql が不適切になるいくつかの変更と微調整が必要です)。クラスは、(属性を使用して) マークされているプロパティを識別して何かを実行しますが、式を LinqToObject プロバイダーに渡して、後で結果をフィルター処理できるようにしたいと考えています。
たとえば、次の linq 式があるとします。
var parents=Context.Parents
.Where(parent=>parent.Name.Contains("T") && parent.Age>18);
Parents クラスは、IQueryProvider および IQueryable インターフェイスを実装するカスタム クラスですが、Age プロパティのみ取得用にマークされているため、Age プロパティは処理されますが、Name プロパティはマークされていないため無視されます。Age プロパティの処理が完了したら、式全体を LinqToObjects に渡して処理とフィルター処理を行いたいのですが、方法がわかりません。
注意: 式の Age 句を削除する必要はありません。これは、処理した後でも結果が同じになるため、常に式全体を LinqToObjects に送信できるためです。
次のコードを試しましたが、うまくいかないようです。
IEnumerator IEnumerable.GetEnumerator() {
if(this.expression != null && !this.isEnumerating) {
this.isEnumerating = true;
var queryable=this.ToList().AsQueryable();
var query = queryable.Provider.CreateQuery(this.expression);
return query.GetEnumerator();
}
return this;
}
this.isEnumrating は、再帰を防ぐために設定された単なるブール フラグです。
this.expression には次が含まれます。
{value(namespace.Parents`1[namespace.Child]).Where(parent => ((parent.Name.EndsWith("T") AndAlso parent.Name.StartsWith("M")) AndAlso (parent.Test > 0)))}
コードをステップ実行すると、結果がリストに変換されますが、それでもクエリにカスタム クラスが使用されます。クラス Parent が式の先頭にあったため、クエリをプロバイダーにルーティングしていたため、 this.expression をメソッド呼び出しの Argument[1] に設定しようとしたため、次のようになりました。
{parent => ((parent.Name.EndsWith("T") AndAlso parent.Name.StartsWith("M")) AndAlso (parent.Test > 0))}
私にはどちらが似ているように見えますが、これを CreateQuery 関数に渡すたびに、「引数式が無効です」というエラーが表示されます。
ただし、式のノード タイプは「Call」ではなく「Quote」になり、メソッドは null です。この式を呼び出し式にするだけでうまくいくと思いますが、どうすればよいかわかりません。
この式は where 句ですが、任意の種類の式である可能性があることに注意してください。リスト クエリ プロバイダーに渡す前に、式を分析して型を確認することは避けたいと思います。
おそらく、元の式の Parent クラスを除去またはリスト プロバイダー クラスに置き換える方法がありますが、式の種類に関係なく、式としてリスト プロバイダーに渡すことができる状態のままにしておく方法はありますか?
これに関する助けがあれば大歓迎です!