Lambda式c#経験談:Expression式を巧みに使用してsqlのselectinのようなクエリーを解決します(中小規模プロジェクトに適しています)


プロジェクトでは、ドロップダウン・ボックスがチェックされているなど、特定の要件に遭遇することがよくあります.クエリーの条件は、ドロップダウン・ボックスの複素オプションに基づいて接続されています.
この図を見て、これは簡単だと言います.
すべてのオプションを「'1-3','5-9'」とつづってinの文の後ろに置いて、調べると出てきます.
これは確かに論理的には問題ありませんが、この問題を考えたことがありますか.過度なビジネス結合は解決できますが.
現在のニーズは、コードの優雅さとメンテナンス性を犠牲にしています.
 
この文書の目的は、Expression式を使用してlinqクエリで優雅なソリューションを実現することです.
同時にExpressionでsqlをつなぎ合わせる考えも与えられます
 
先着コード
      public static Expression<Func<T, bool>> GetConditionExpression<T>(string[] options, string fieldName)
        {
            ParameterExpression left = Expression.Parameter(typeof(T), "c");//c=>
            Expression expression = Expression.Constant(false);
            foreach (var optionName in options)
            {
                Expression right = Expression.Call
                       (
                          Expression.Property(left, typeof(T).GetProperty(fieldName)),  //c.DataSourceName
                          typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),//     .Contains()                           
                         s Expression.Constant(optionName)           // .Contains(optionName)
                       );
                expression = Expression.Or(right, expression);//c.DataSourceName.contain("") || c.DataSourceName.contain("") 
            }
            Expression<Func<T, bool>> finalExpression
                = Expression.Lambda<Func<T, bool>>(expression, new ParameterExpression[] { left });
            return finalExpression;
        }

このコードを逆プッシュで説明したいのですが、実は私たちのクエリーの目的はこのような効果を実現することです.someList.where(c=>c.Name.contains("someName")||c.Name.Contains("someName")||...)
1.まず、経験に基づいて、どのような式を返すかを決定します.whereの後にはExpressionという表現が必要なので,メソッドの戻りタイプはすでに決定されている.
2.次のタスクはc=>c.Nameに類似する接合です.Contains("")のような表現は、左から右への原則に従って、左側の表現パラメータcがTであることをよく理解すれば、この表現のパラメータもできます.
Expressionを使用できます.パラメータメソッドは、タイプを反射して式にマッピングする匿名変数「c」を実現する(パラメータ定数を式にカプセル化することも理解できる)
3.次は式の右側のつづり
もう一度このコードをよく見てみましょう
Expression right = Expression.Call 
 (                          
     Expression.Property(left, typeof(T).GetProperty(fieldName),//c.DataSourceNameは、cを取得するために反射するプロパティです.
     typeof(string).GetMethod("Contains",new Type[]{typeof(string)})//stringを宣言します.Containsの方法c.DataSourceName.Contains()反射使用.Contains()メソッド
     Expression.Constant(optionName)           // c.DataSourceName.Contains(optionName)パッケージ定数
 );
なぜExpressionを使うのか.Call ?
(c.Name.containsはstring.contains()に属するので、この方法を式、Expressionにカプセル化する必要があります.Callの機能はメソッドを式にカプセル化することです)
この時みんなはcontainsに何を聞きますか?もちろん定数optionはstringタイプですが、式、Expressionにカプセル化する必要があります.Constant(optionName)はパッケージ定数の役割を果たしています
するとc=>c.の属性となる.Contains(定数)という表現はできましたが、どうやって「|」を加えるのか、賢いあなたはすでに答えを持っています.Expression.Or()
 
4最後のステップはもちろん重要です.製品が流水ラインで包装する必要があるように、式も例外ではありません.
Expression.Lambda>(expression, new ParameterExpression[] { left });
式全体の場合、左側はパラメータ式(ParameterExpression)、Expression.Lambdaは=>記号で、右側の式とパラメータ式をlambda記号で組み合わせることで
 
これにより、文字列配列を1つ入力するだけで、sqlのselectinのような効果をLinqで実現できます.
多くの友达は、カスタム式でできる以上、式の考え方をsqlのつなぎ合わせに使ってもいいですかと聞くに違いありません.
答えは肯定的だ.しかし、ビジネスロジックが複雑で把握しにくい場合は、ado協力で実現することをお勧めします.
 
 
彼女に感谢してずっと深夜まで付き添って、私に坚持してこの博文を书き终わらせて、文の中でもし间违いがあるならば、同じくみんなに大目に见てそして直ちに私に教えてもらうことができて、ありがとうございます!